diff --git a/.github/ISSUE_TEMPLATE/rustdoc.md b/.github/ISSUE_TEMPLATE/rustdoc.md new file mode 100644 index 000000000000..130d5f67102a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/rustdoc.md @@ -0,0 +1,54 @@ +--- +name: Problem with rustdoc +about: Report an issue with how docs get generated. +labels: C-bug, T-rustdoc +--- + + +# Code + + +```rust + +``` + +# Reproduction Steps + + +# Expected Outcome + + +# Actual Output + +```console + +``` + + +# Version + + +# Additional Details + diff --git a/.mailmap b/.mailmap index b9fb7be0403c..2a53cbf9effc 100644 --- a/.mailmap +++ b/.mailmap @@ -162,8 +162,10 @@ David Carlier David Klein David Manescu David Ross -David Wood +David Wood +David Wood David Wood +David Wood Deadbeef Deadbeef dependabot[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> @@ -698,3 +700,4 @@ Zach Pomerantz Zack Corr Zack Slayton Zbigniew Siciarz Zbigniew Siciarz +y21 <30553356+y21@users.noreply.github.com> diff --git a/Cargo.lock b/Cargo.lock index 4d95f5e11b2c..e95cacf1f6d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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]] @@ -2983,6 +2983,15 @@ dependencies = [ "getrandom 0.3.3", ] +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.3", +] + [[package]] name = "rand_xoshiro" version = "0.7.0" @@ -3014,9 +3023,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 +3157,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" @@ -3166,9 +3175,9 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc-literal-escaper" -version = "0.0.2" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04" +checksum = "ab03008eb631b703dd16978282ae36c73282e7922fe101a4bd072a40ecea7b8b" [[package]] name = "rustc-main" @@ -3182,16 +3191,6 @@ dependencies = [ "tikv-jemalloc-sys", ] -[[package]] -name = "rustc-rayon-core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f42932dcd3bcbe484b38a3ccf79b7906fac41c02d408b5b1bac26da3416efdb" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - [[package]] name = "rustc-semver" version = "1.1.0" @@ -3283,6 +3282,7 @@ dependencies = [ "rustc_abi", "rustc_ast", "rustc_ast_pretty", + "rustc_attr_data_structures", "rustc_attr_parsing", "rustc_data_structures", "rustc_errors", @@ -3317,6 +3317,7 @@ dependencies = [ "rustc_parse", "rustc_session", "rustc_span", + "rustc_target", "thin-vec", ] @@ -3440,7 +3441,7 @@ dependencies = [ "itertools", "libc", "measureme", - "object 0.37.0", + "object 0.37.1", "rustc-demangle", "rustc_abi", "rustc_ast", @@ -3479,7 +3480,7 @@ dependencies = [ "cc", "itertools", "libc", - "object 0.37.0", + "object 0.37.1", "pathdiff", "regex", "rustc_abi", @@ -3558,7 +3559,6 @@ dependencies = [ "parking_lot", "portable-atomic", "rustc-hash 2.1.1", - "rustc-rayon-core", "rustc-stable-hash", "rustc_arena", "rustc_graphviz", @@ -3566,6 +3566,7 @@ dependencies = [ "rustc_index", "rustc_macros", "rustc_serialize", + "rustc_thread_pool", "smallvec", "stacker", "tempfile", @@ -3656,7 +3657,6 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", - "smallvec", "tracing", "unic-langid", ] @@ -3724,6 +3724,7 @@ dependencies = [ name = "rustc_feature" version = "0.0.0" dependencies = [ + "rustc_attr_data_structures", "rustc_data_structures", "rustc_span", "serde", @@ -3739,7 +3740,7 @@ dependencies = [ "fluent-syntax", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", "unic-langid", ] @@ -3888,7 +3889,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -3913,7 +3914,6 @@ dependencies = [ name = "rustc_interface" version = "0.0.0" dependencies = [ - "rustc-rayon-core", "rustc_abi", "rustc_ast", "rustc_ast_lowering", @@ -3952,6 +3952,7 @@ dependencies = [ "rustc_span", "rustc_symbol_mangling", "rustc_target", + "rustc_thread_pool", "rustc_trait_selection", "rustc_traits", "rustc_ty_utils", @@ -4035,7 +4036,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", "synstructure", ] @@ -4079,7 +4080,6 @@ dependencies = [ "either", "gsgdt", "polonius-engine", - "rustc-rayon-core", "rustc_abi", "rustc_apfloat", "rustc_arena", @@ -4103,6 +4103,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", + "rustc_thread_pool", "rustc_type_ir", "smallvec", "thin-vec", @@ -4118,6 +4119,7 @@ dependencies = [ "rustc_apfloat", "rustc_arena", "rustc_ast", + "rustc_attr_data_structures", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -4240,7 +4242,7 @@ dependencies = [ "thin-vec", "tracing", "unicode-normalization", - "unicode-width 0.2.0", + "unicode-width 0.2.1", ] [[package]] @@ -4349,7 +4351,6 @@ version = "0.0.0" dependencies = [ "hashbrown", "parking_lot", - "rustc-rayon-core", "rustc_abi", "rustc_ast", "rustc_attr_data_structures", @@ -4364,6 +4365,7 @@ dependencies = [ "rustc_serialize", "rustc_session", "rustc_span", + "rustc_thread_pool", "smallvec", "tracing", ] @@ -4447,7 +4449,6 @@ dependencies = [ "rustc_serialize", "rustc_span", "rustc_target", - "smallvec", "termize", "tracing", "windows", @@ -4489,7 +4490,7 @@ dependencies = [ "sha1", "sha2", "tracing", - "unicode-width 0.2.0", + "unicode-width 0.2.1", ] [[package]] @@ -4514,7 +4515,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", @@ -4525,6 +4526,18 @@ dependencies = [ "tracing", ] +[[package]] +name = "rustc_thread_pool" +version = "0.0.0" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", + "libc", + "rand 0.9.1", + "rand_xorshift", + "scoped-tls", +] + [[package]] name = "rustc_tools_util" version = "0.4.2" @@ -4635,7 +4648,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", "synstructure", ] @@ -4726,7 +4739,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -4854,7 +4867,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -5094,9 +5107,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 +5124,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -5244,7 +5257,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -5255,7 +5268,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -5272,12 +5285,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 +5443,7 @@ checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -5602,7 +5614,7 @@ checksum = "a1249a628de3ad34b821ecb1001355bca3940bcb2f88558f1a8bd82e977f75b5" dependencies = [ "proc-macro-hack", "quote", - "syn 2.0.101", + "syn 2.0.103", "unic-langid-impl", ] @@ -5670,9 +5682,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 +5785,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" @@ -5788,9 +5800,9 @@ dependencies = [ [[package]] name = "wasi-preview1-component-adapter-provider" -version = "31.0.0" +version = "34.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fabda09a0d89ffd1615b297b4a5d4b4d99df9598aeb24685837e63019e927b" +checksum = "aafa1e6af9a954a4bcf6ef420c33355d0ce84ddc6afbcba7bb6f05126f9120ae" [[package]] name = "wasm-bindgen" @@ -5814,7 +5826,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", "wasm-bindgen-shared", ] @@ -5836,7 +5848,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5852,9 +5864,9 @@ dependencies = [ [[package]] name = "wasm-component-ld" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a60a07a994a3538b57d8c5f8caba19f4793fb4c7156276e5e90e90acbb829e20" +checksum = "b015ec93764aa5517bc8b839efa9941b90be8ce680b1134f8224644ba1e48e3f" dependencies = [ "anyhow", "clap", @@ -5862,7 +5874,7 @@ dependencies = [ "libc", "tempfile", "wasi-preview1-component-adapter-provider", - "wasmparser 0.229.0", + "wasmparser 0.234.0", "wat", "windows-sys 0.59.0", "winsplit", @@ -5889,34 +5901,34 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.229.0" +version = "0.234.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ba1d491ecacb085a2552025c10a675a6fddcbd03b1fc9b36c536010ce265d2" +checksum = "170a0157eef517a179f2d20ed7c68df9c3f7f6c1c047782d488bf5a464174684" dependencies = [ "leb128fmt", - "wasmparser 0.229.0", + "wasmparser 0.234.0", ] [[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]] name = "wasm-metadata" -version = "0.229.0" +version = "0.234.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78fdb7d29a79191ab363dc90c1ddd3a1e880ffd5348d92d48482393a9e6c5f4d" +checksum = "a42fe3f5cbfb56fc65311ef827930d06189160038e81db62188f66b4bf468e3a" dependencies = [ "anyhow", "indexmap", - "wasm-encoder 0.229.0", - "wasmparser 0.229.0", + "wasm-encoder 0.234.0", + "wasmparser 0.234.0", ] [[package]] @@ -5931,9 +5943,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.229.0" +version = "0.234.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc3b1f053f5d41aa55640a1fa9b6d1b8a9e4418d118ce308d20e24ff3575a8c" +checksum = "be22e5a8f600afce671dd53c8d2dd26b4b7aa810fd18ae27dfc49737f3e02fc5" dependencies = [ "bitflags", "hashbrown", @@ -5944,18 +5956,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.232.0" +version = "0.235.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917739b33bb1eb0e9a49bcd2637a351931be4578d0cc4d37b908d7a797784fbb" -dependencies = [ - "bitflags", -] - -[[package]] -name = "wasmparser" -version = "0.233.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b51cb03afce7964bbfce46602d6cb358726f36430b6ba084ac6020d8ce5bc102" +checksum = "161296c618fa2d63f6ed5fffd1112937e803cb9ec71b32b01a76321555660917" dependencies = [ "bitflags", "indexmap", @@ -5964,22 +5967,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 +6030,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 +6093,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -6101,14 +6104,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 +6168,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 +6210,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 +6382,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", ] @@ -6394,9 +6406,9 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.229.0" +version = "0.234.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f550067740e223bfe6c4878998e81cdbe2529dd9a793dc49248dd6613394e8b" +checksum = "5a8888169acf4c6c4db535beb405b570eedac13215d6821ca9bd03190f7f8b8c" dependencies = [ "anyhow", "bitflags", @@ -6405,17 +6417,17 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.229.0", + "wasm-encoder 0.234.0", "wasm-metadata", - "wasmparser 0.229.0", + "wasmparser 0.234.0", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.229.0" +version = "0.234.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459c6ba62bf511d6b5f2a845a2a736822e38059c1cfa0b644b467bbbfae4efa6" +checksum = "465492df47d8dcc015a3b7f241aed8ea03688fee7c5e04162285c5b1a3539c8b" dependencies = [ "anyhow", "id-arena", @@ -6426,7 +6438,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.229.0", + "wasmparser 0.234.0", ] [[package]] @@ -6505,7 +6517,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", "synstructure", ] @@ -6517,7 +6529,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", "synstructure", ] @@ -6538,7 +6550,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -6558,7 +6570,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", "synstructure", ] @@ -6603,7 +6615,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] [[package]] @@ -6614,5 +6626,5 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.103", ] diff --git a/Cargo.toml b/Cargo.toml index c4d2a06f4cb1..6d3425f4115a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,7 +60,7 @@ exclude = [ "obj", ] -[profile.release.package.rustc-rayon-core] +[profile.release.package.rustc_thread_pool] # The rustc fork of Rayon has deadlock detection code which intermittently # causes overflows in the CI (see https://github.com/rust-lang/rust/issues/90227) # so we turn overflow checks off for now. @@ -89,3 +89,8 @@ codegen-units = 1 # FIXME: LTO cannot be enabled for binaries in a workspace # # lto = true + +# If you want to use a crate with local modifications, you can set a path or git dependency here. +# For git dependencies, also add your source to ALLOWED_SOURCES in src/tools/tidy/src/extdeps.rs. +#[patch.crates-io] + diff --git a/RELEASES.md b/RELEASES.md index 3c72cb1de0a3..8a6bb214d2d5 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,103 @@ +Version 1.88.0 (2025-06-26) +========================== + + + +Language +-------- +- [Stabilize `#![feature(let_chains)]` in the 2024 edition.](https://github.com/rust-lang/rust/pull/132833) + This feature allows `&&`-chaining `let` statements inside `if` and `while`, allowing intermixture with boolean expressions. The patterns inside the `let` sub-expressions can be irrefutable or refutable. +- [Stabilize `#![feature(naked_functions)]`.](https://github.com/rust-lang/rust/pull/134213) + Naked functions allow writing functions with no compiler-generated epilogue and prologue, allowing full control over the generated assembly for a particular function. +- [Stabilize `#![feature(cfg_boolean_literals)]`.](https://github.com/rust-lang/rust/pull/138632) + This allows using boolean literals as `cfg` predicates, e.g. `#[cfg(true)]` and `#[cfg(false)]`. +- [Fully de-stabilize the `#[bench]` attribute](https://github.com/rust-lang/rust/pull/134273). Usage of `#[bench]` without `#![feature(custom_test_frameworks)]` already triggered a deny-by-default future-incompatibility lint since Rust 1.77, but will now become a hard error. +- [Add warn-by-default `dangerous_implicit_autorefs` lint against implicit autoref of raw pointer dereference.](https://github.com/rust-lang/rust/pull/123239) + The lint [will be bumped to deny-by-default](https://github.com/rust-lang/rust/pull/141661) in the next version of Rust. +- [Add `invalid_null_arguments` lint to prevent invalid usage of null pointers.](https://github.com/rust-lang/rust/pull/119220) + This lint is uplifted from `clippy::invalid_null_ptr_usage`. +- [Change trait impl candidate preference for builtin impls and trivial where-clauses.](https://github.com/rust-lang/rust/pull/138176) +- [Check types of generic const parameter defaults](https://github.com/rust-lang/rust/pull/139646) + + + +Compiler +-------- +- [Stabilize `-Cdwarf-version` for selecting the version of DWARF debug information to generate.](https://github.com/rust-lang/rust/pull/136926) + + + + +Platform Support +---------------- +- [Demote `i686-pc-windows-gnu` to Tier 2.](https://blog.rust-lang.org/2025/05/26/demoting-i686-pc-windows-gnu/) + + +Refer to Rust's [platform support page][platform-support-doc] +for more information on Rust's tiered platform support. + +[platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html + + + +Libraries +--------- +- [Remove backticks from `#[should_panic]` test failure message.](https://github.com/rust-lang/rust/pull/136160) +- [Guarantee that `[T; N]::from_fn` is generated in order of increasing indices.](https://github.com/rust-lang/rust/pull/139099), for those passing it a stateful closure. +- [The libtest flag `--nocapture` is deprecated in favor of the more consistent `--no-capture` flag.](https://github.com/rust-lang/rust/pull/139224) +- [Guarantee that `{float}::NAN` is a quiet NaN.](https://github.com/rust-lang/rust/pull/139483) + + + + +Stabilized APIs +--------------- + +- [`Cell::update`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#method.update) +- [`impl Default for *const T`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#impl-Default-for-*const+T) +- [`impl Default for *mut T`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#impl-Default-for-*mut+T) +- [`HashMap::extract_if`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html#method.extract_if) +- [`HashSet::extract_if`](https://doc.rust-lang.org/stable/std/collections/struct.HashSet.html#method.extract_if) +- [`proc_macro::Span::line`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.line) +- [`proc_macro::Span::column`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.column) +- [`proc_macro::Span::start`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.start) +- [`proc_macro::Span::end`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.end) +- [`proc_macro::Span::file`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.file) +- [`proc_macro::Span::local_file`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.local_file) + +These previously stable APIs are now stable in const contexts: + +- [`NonNull::replace`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.replace) +- [`<*mut T>::replace`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.replace) +- [`std::ptr::swap_nonoverlapping`](https://github.com/rust-lang/rust/pull/137280) +- [`Cell::{replace, get, get_mut, from_mut, as_slice_of_cells}`](https://github.com/rust-lang/rust/pull/137928) + + + + +Cargo +----- +- [Stabilize automatic garbage collection.](https://github.com/rust-lang/cargo/pull/14287/) +- [use `zlib-rs` for gzip compression in rust code](https://github.com/rust-lang/cargo/pull/15417/) + + + +Rustdoc +----- +- [Doctests can be ignored based on target names using `ignore-*` attributes.](https://github.com/rust-lang/rust/pull/137096) +- [Stabilize the `--test-runtool` and `--test-runtool-arg` CLI options to specify a program (like qemu) and its arguments to run a doctest.](https://github.com/rust-lang/rust/pull/137096) + + + +Compatibility Notes +------------------- +- [Finish changing the internal representation of pasted tokens](https://github.com/rust-lang/rust/pull/124141). Certain invalid declarative macros that were previously accepted in obscure circumstances are now correctly rejected by the compiler. Use of a `tt` fragment specifier can often fix these macros. +- [Fully de-stabilize the `#[bench]` attribute](https://github.com/rust-lang/rust/pull/134273). Usage of `#[bench]` without `#![feature(custom_test_frameworks)]` already triggered a deny-by-default future-incompatibility lint since Rust 1.77, but will now become a hard error. +- [Fix borrow checking some always-true patterns.](https://github.com/rust-lang/rust/pull/139042) + The borrow checker was overly permissive in some cases, allowing programs that shouldn't have compiled. +- [Update the minimum external LLVM to 19.](https://github.com/rust-lang/rust/pull/139275) +- [Make it a hard error to use a vector type with a non-Rust ABI without enabling the required target feature.](https://github.com/rust-lang/rust/pull/139309) + Version 1.87.0 (2025-05-15) ========================== diff --git a/bootstrap.example.toml b/bootstrap.example.toml index 19cf360b0fb8..cc1ea796a028 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -8,6 +8,14 @@ # `bootstrap.toml` in the current directory of a build for build configuration, but # a custom configuration file can also be specified with `--config` to the build # system. +# +# Note that the following are equivelent, for more details see . +# +# build.verbose = 1 +# +# [build] +# verbose = 1 + # ============================================================================= # Global Settings @@ -44,7 +52,6 @@ # ============================================================================= # Tweaking how LLVM is compiled # ============================================================================= -[llvm] # Whether to use Rust CI built LLVM instead of locally building it. # @@ -62,50 +69,50 @@ # # Note that many of the LLVM options are not currently supported for # downloading. Currently only the "assertions" option can be toggled. -#download-ci-llvm = true +#llvm.download-ci-llvm = true # Indicates whether the LLVM build is a Release or Debug build -#optimize = true +#llvm.optimize = true # Indicates whether LLVM should be built with ThinLTO. Note that this will # only succeed if you use clang, lld, llvm-ar, and llvm-ranlib in your C/C++ # toolchain (see the `cc`, `cxx`, `linker`, `ar`, and `ranlib` options below). # More info at: https://clang.llvm.org/docs/ThinLTO.html#clang-bootstrap -#thin-lto = false +#llvm.thin-lto = false # Indicates whether an LLVM Release build should include debug info -#release-debuginfo = false +#llvm.release-debuginfo = false # Indicates whether the LLVM assertions are enabled or not # NOTE: When assertions are disabled, bugs in the integration between rustc and LLVM can lead to # unsoundness (segfaults, etc.) in the rustc process itself, not just in the generated code. -#assertions = false +#llvm.assertions = false # Indicates whether the LLVM testsuite is enabled in the build or not. Does # not execute the tests as part of the build as part of x.py build et al, # just makes it possible to do `ninja check-llvm` in the staged LLVM build # directory when doing LLVM development as part of Rust development. -#tests = false +#llvm.tests = false # Indicates whether the LLVM plugin is enabled or not -#plugins = false +#llvm.plugins = false # Whether to build Enzyme as AutoDiff backend. -#enzyme = false +#llvm.enzyme = false # Whether to build LLVM with support for it's gpu offload runtime. -#offload = false +#llvm.offload = false # When true, link libstdc++ statically into the rustc_llvm. # This is useful if you don't want to use the dynamic version of that # library provided by LLVM. -#static-libstdcpp = false +#llvm.static-libstdcpp = false # Enable LLVM to use zstd for compression. -#libzstd = false +#llvm.libzstd = false # Whether to use Ninja to build LLVM. This runs much faster than make. -#ninja = true +#llvm.ninja = true # LLVM targets to build support for. # Note: this is NOT related to Rust compilation targets. However, as Rust is @@ -113,13 +120,13 @@ # the resulting rustc being unable to compile for the disabled architectures. # # To add support for new targets, see https://rustc-dev-guide.rust-lang.org/building/new-target.html. -#targets = "AArch64;AMDGPU;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86" +#llvm.targets = "AArch64;AMDGPU;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86" # LLVM experimental targets to build support for. These targets are specified in # the same format as above, but since these targets are experimental, they are # not built by default and the experimental Rust compilation targets that depend # on them will not work unless the user opts in to building them. -#experimental-targets = "AVR;M68k;CSKY" +#llvm.experimental-targets = "AVR;M68k;CSKY" # Cap the number of parallel linker invocations when compiling LLVM. # This can be useful when building LLVM with debug info, which significantly @@ -127,86 +134,84 @@ # each linker process. # If set to 0, linker invocations are treated like any other job and # controlled by bootstrap's -j parameter. -#link-jobs = 0 +#llvm.link-jobs = 0 # Whether to build LLVM as a dynamically linked library (as opposed to statically linked). # Under the hood, this passes `--shared` to llvm-config. # NOTE: To avoid performing LTO multiple times, we suggest setting this to `true` when `thin-lto` is enabled. -#link-shared = llvm.thin-lto +#llvm.link-shared = llvm.thin-lto # When building llvm, this configures what is being appended to the version. # To use LLVM version as is, provide an empty string. -#version-suffix = if rust.channel == "dev" { "-rust-dev" } else { "-rust-$version-$channel" } +#llvm.version-suffix = if rust.channel == "dev" { "-rust-dev" } else { "-rust-$version-$channel" } # On MSVC you can compile LLVM with clang-cl, but the test suite doesn't pass # with clang-cl, so this is special in that it only compiles LLVM with clang-cl. # Note that this takes a /path/to/clang-cl, not a boolean. -#clang-cl = cc +#llvm.clang-cl = cc # Pass extra compiler and linker flags to the LLVM CMake build. -#cflags = "" -#cxxflags = "" -#ldflags = "" +#llvm.cflags = "" +#llvm.cxxflags = "" +#llvm.ldflags = "" # Use libc++ when building LLVM instead of libstdc++. This is the default on # platforms already use libc++ as the default C++ library, but this option # allows you to use libc++ even on platforms when it's not. You need to ensure # that your host compiler ships with libc++. -#use-libcxx = false +#llvm.use-libcxx = false # The value specified here will be passed as `-DLLVM_USE_LINKER` to CMake. -#use-linker = (path) +#llvm.use-linker = (path) # Whether or not to specify `-DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=YES` -#allow-old-toolchain = false +#llvm.allow-old-toolchain = false # Whether to include the Polly optimizer. -#polly = false +#llvm.polly = false # Whether to build the clang compiler. -#clang = false +#llvm.clang = false # Whether to enable llvm compilation warnings. -#enable-warnings = false +#llvm.enable-warnings = false # Custom CMake defines to set when building LLVM. -#build-config = {} +#llvm.build-config = {} # ============================================================================= # Tweaking how GCC is compiled # ============================================================================= -[gcc] # Download GCC from CI instead of building it locally. # Note that this will attempt to download GCC even if there are local # modifications to the `src/gcc` submodule. # Currently, this is only supported for the `x86_64-unknown-linux-gnu` target. -#download-ci-gcc = false +#gcc.download-ci-gcc = false # ============================================================================= # General build configuration options # ============================================================================= -[build] # The default stage to use for the `check` subcommand -#check-stage = 0 +#build.check-stage = 0 # The default stage to use for the `doc` subcommand -#doc-stage = 0 +#build.doc-stage = 0 # The default stage to use for the `build` subcommand -#build-stage = 1 +#build.build-stage = 1 # The default stage to use for the `test` subcommand -#test-stage = 1 +#build.test-stage = 1 # The default stage to use for the `dist` subcommand -#dist-stage = 2 +#build.dist-stage = 2 # The default stage to use for the `install` subcommand -#install-stage = 2 +#build.install-stage = 2 # The default stage to use for the `bench` subcommand -#bench-stage = 2 +#build.bench-stage = 2 # A descriptive string to be appended to version output (e.g., `rustc --version`), # which is also used in places like debuginfo `DW_AT_producer`. This may be useful for @@ -217,7 +222,7 @@ # upstream Rust you need to set this to "". However, note that if you set this to "" but # are not actually compatible -- for example if you've backported patches that change # behavior -- this may lead to miscompilations or other bugs. -#description = "" +#build.description = "" # Build triple for the pre-compiled snapshot compiler. If `rustc` is set, this must match its host # triple (see `rustc --version --verbose`; cross-compiling the rust build system itself is NOT @@ -229,14 +234,14 @@ # Otherwise, `x.py` will try to infer it from the output of `uname`. # If `uname` is not found in PATH, we assume this is `x86_64-pc-windows-msvc`. # This may be changed in the future. -#build = "x86_64-unknown-linux-gnu" (as an example) +#build.build = "x86_64-unknown-linux-gnu" (as an example) # Which triples to produce a compiler toolchain for. Each of these triples will be bootstrapped from # the build triple themselves. In other words, this is the list of triples for which to build a # compiler that can RUN on that triple. # # Defaults to just the `build` triple. -#host = [build.build] (list of triples) +#build.host = [build.build] (list of triples) # Which triples to build libraries (core/alloc/std/test/proc_macro) for. Each of these triples will # be bootstrapped from the build triple themselves. In other words, this is the list of triples for @@ -245,32 +250,32 @@ # Defaults to `host`. If you set this explicitly, you likely want to add all # host triples to this list as well in order for those host toolchains to be # able to compile programs for their native target. -#target = build.host (list of triples) +#build.target = build.host (list of triples) # Use this directory to store build artifacts. Paths are relative to the current directory, not to # the root of the repository. -#build-dir = "build" +#build.build-dir = "build" # Instead of downloading the src/stage0 version of Cargo specified, use # this Cargo binary instead to build all Rust code # If you set this, you likely want to set `rustc` as well. -#cargo = "/path/to/cargo" +#build.cargo = "/path/to/cargo" # Instead of downloading the src/stage0 version of the compiler # specified, use this rustc binary instead as the stage0 snapshot compiler. # If you set this, you likely want to set `cargo` as well. -#rustc = "/path/to/rustc" +#build.rustc = "/path/to/rustc" # Instead of downloading the src/stage0 version of rustfmt specified, # use this rustfmt binary instead as the stage0 snapshot rustfmt. -#rustfmt = "/path/to/rustfmt" +#build.rustfmt = "/path/to/rustfmt" # Instead of downloading the src/stage0 version of cargo-clippy specified, # use this cargo-clippy binary instead as the stage0 snapshot cargo-clippy. # # Note that this option should be used with the same toolchain as the `rustc` option above. # Otherwise, clippy is likely to fail due to a toolchain conflict. -#cargo-clippy = "/path/to/cargo-clippy" +#build.cargo-clippy = "/path/to/cargo-clippy" # Whether to build documentation by default. If false, rustdoc and # friends will still be compiled but they will not be used to generate any @@ -278,47 +283,47 @@ # # You can still build documentation when this is disabled by explicitly passing paths, # e.g. `x doc library`. -#docs = true +#build.docs = true # Flag to specify whether CSS, JavaScript, and HTML are minified when # docs are generated. JSON is always minified, because it's enormous, # and generated in already-minified form from the beginning. -#docs-minification = true +#build.docs-minification = true # Flag to specify whether private items should be included in the library docs. -#library-docs-private-items = false +#build.library-docs-private-items = false # Indicate whether to build compiler documentation by default. # You can still build documentation when this is disabled by explicitly passing a path: `x doc compiler`. -#compiler-docs = false +#build.compiler-docs = false # Indicate whether git submodules are managed and updated automatically. -#submodules = true +#build.submodules = true # The path to (or name of) the GDB executable to use. This is only used for # executing the debuginfo test suite. -#gdb = "gdb" +#build.gdb = "gdb" # The path to (or name of) the LLDB executable to use. This is only used for # executing the debuginfo test suite. -#lldb = "lldb" +#build.lldb = "lldb" # The node.js executable to use. Note that this is only used for the emscripten # target when running tests, otherwise this can be omitted. -#nodejs = "node" +#build.nodejs = "node" # The npm executable to use. Note that this is used for rustdoc-gui tests, # otherwise this can be omitted. # # Under Windows this should be `npm.cmd` or path to it (verified on nodejs v18.06), or # error will be emitted. -#npm = "npm" +#build.npm = "npm" # Python interpreter to use for various tasks throughout the build, notably # rustdoc tests, the lldb python interpreter, and some dist bits and pieces. # # Defaults to the Python interpreter used to execute x.py. -#python = "python" +#build.python = "python" # The path to the REUSE executable to use. Note that REUSE is not required in # most cases, as our tooling relies on a cached (and shrunk) copy of the @@ -328,17 +333,17 @@ # repository to change, and the cached copy has to be regenerated. # # Defaults to the "reuse" command in the system path. -#reuse = "reuse" +#build.reuse = "reuse" # Force Cargo to check that Cargo.lock describes the precise dependency # set that all the Cargo.toml files create, instead of updating it. -#locked-deps = false +#build.locked-deps = false # Indicate whether the vendored sources are used for Rust dependencies or not. # # Vendoring requires additional setup. We recommend using the pre-generated source tarballs if you # want to use vendoring. See https://forge.rust-lang.org/infra/other-installation-methods.html#source-code. -#vendor = if "is a tarball source" && "vendor" dir exists && ".cargo/config.toml" file exists { true } else { false } +#build.vendor = if "is a tarball source" && "vendor" dir exists && ".cargo/config.toml" file exists { true } else { false } # Typically the build system will build the Rust compiler twice. The second # compiler, however, will simply use its own libraries to link against. If you @@ -346,11 +351,11 @@ # then you can set this option to true. # # This is only useful for verifying that rustc generates reproducible builds. -#full-bootstrap = false +#build.full-bootstrap = false # Set the bootstrap/download cache path. It is useful when building rust # repeatedly in a CI environment. -#bootstrap-cache-path = /path/to/shared/cache +#build.bootstrap-cache-path = /path/to/shared/cache # Enable a build of the extended Rust tool set which is not only the compiler # but also tools such as Cargo. This will also produce "combined installers" @@ -359,7 +364,7 @@ # which tools should be built if `extended = true`. # # This is disabled by default. -#extended = false +#build.extended = false # Set of tools to be included in the installation. # @@ -368,7 +373,7 @@ # If `extended = true`, they are all included. # # If any enabled tool fails to build, the installation fails. -#tools = [ +#build.tools = [ # "cargo", # "clippy", # "rustdoc", @@ -388,17 +393,17 @@ # # The default value for the `features` array is `[]`. However, please note that other flags in # `bootstrap.toml` might influence the features enabled for some tools. -#tool.TOOL_NAME.features = [FEATURE1, FEATURE2] +#build.tool.TOOL_NAME.features = [FEATURE1, FEATURE2] # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose, 3 == print environment variables on each rustc invocation -#verbose = 0 +#build.verbose = 0 # Build the sanitizer runtimes -#sanitizers = false +#build.sanitizers = false # Build the profiler runtime (required when compiling with options that depend # on this runtime, such as `-C profile-generate` or `-C instrument-coverage`). -#profiler = false +#build.profiler = false # Use the optimized LLVM C intrinsics for `compiler_builtins`, rather than Rust intrinsics. # Requires the LLVM submodule to be managed by bootstrap (i.e. not external) so that `compiler-rt` @@ -406,102 +411,100 @@ # # Setting this to `false` generates slower code, but removes the requirement for a C toolchain in # order to run `x check`. -#optimized-compiler-builtins = if rust.channel == "dev" { false } else { true } +#build.optimized-compiler-builtins = if rust.channel == "dev" { false } else { true } # Indicates whether the native libraries linked into Cargo will be statically # linked or not. -#cargo-native-static = false +#build.cargo-native-static = false # Run the build with low priority, by setting the process group's "nice" value # to +10 on Unix platforms, and by using a "low priority" job object on Windows. -#low-priority = false +#build.low-priority = false # Arguments passed to the `./configure` script, used during distcheck. You # probably won't fill this in but rather it's filled in by the `./configure` # script. Useful for debugging. -#configure-args = [] +#build.configure-args = [] # Indicates that a local rebuild is occurring instead of a full bootstrap, # essentially skipping stage0 as the local compiler is recompiling itself again. # Useful for modifying only the stage2 compiler without having to pass `--keep-stage 0` each time. -#local-rebuild = false +#build.local-rebuild = false # Print out how long each bootstrap step took (mostly intended for CI and # tracking over time) -#print-step-timings = false +#build.print-step-timings = false # Print out resource usage data for each bootstrap step, as defined by the Unix # struct rusage. (Note that this setting is completely unstable: the data it # captures, what platforms it supports, the format of its associated output, and # this setting's very existence, are all subject to change.) -#print-step-rusage = false +#build.print-step-rusage = false # Always patch binaries for usage with Nix toolchains. If `true` then binaries # will be patched unconditionally. If `false` or unset, binaries will be patched # only if the current distribution is NixOS. This option is useful when using # a Nix toolchain on non-NixOS distributions. -#patch-binaries-for-nix = false +#build.patch-binaries-for-nix = false # Collect information and statistics about the current build, and write it to # disk. Enabling this has no impact on the resulting build output. The # schema of the file generated by the build metrics feature is unstable, and # this is not intended to be used during local development. -#metrics = false +#build.metrics = false # Specify the location of the Android NDK. Used when targeting Android. -#android-ndk = "/path/to/android-ndk-r26d" +#build.android-ndk = "/path/to/android-ndk-r26d" # Number of parallel jobs to be used for building and testing. If set to `0` or # omitted, it will be automatically determined. This is the `-j`/`--jobs` flag # passed to cargo invocations. -#jobs = 0 +#build.jobs = 0 # What custom diff tool to use for displaying compiletest tests. -#compiletest-diff-tool = +#build.compiletest-diff-tool = # Whether to use the precompiled stage0 libtest with compiletest. -#compiletest-use-stage0-libtest = true +#build.compiletest-use-stage0-libtest = true # Indicates whether ccache is used when building certain artifacts (e.g. LLVM). # Set to `true` to use the first `ccache` in PATH, or set an absolute path to use # a specific version. -#ccache = false +#build.ccache = false # List of paths to exclude from the build and test processes. # For example, exclude = ["tests/ui", "src/tools/tidy"]. -#exclude = [] +#build.exclude = [] # ============================================================================= # General install configuration options # ============================================================================= -[install] # Where to install the generated toolchain. Must be an absolute path. -#prefix = "/usr/local" +#install.prefix = "/usr/local" # Where to install system configuration files. # If this is a relative path, it will get installed in `prefix` above -#sysconfdir = "/etc" +#install.sysconfdir = "/etc" # Where to install documentation in `prefix` above -#docdir = "share/doc/rust" +#install.docdir = "share/doc/rust" # Where to install binaries in `prefix` above -#bindir = "bin" +#install.bindir = "bin" # Where to install libraries in `prefix` above -#libdir = "lib" +#install.libdir = "lib" # Where to install man pages in `prefix` above -#mandir = "share/man" +#install.mandir = "share/man" # Where to install data in `prefix` above -#datadir = "share" +#install.datadir = "share" # ============================================================================= # Options for compiling Rust code itself # ============================================================================= -[rust] # Whether or not to optimize when compiling the compiler and standard library, # and what level of optimization to use. @@ -517,7 +520,7 @@ # 3 - All optimizations. # "s" - Optimize for binary size. # "z" - Optimize for binary size, but also turn off loop vectorization. -#optimize = true +#rust.optimize = true # Indicates that the build should be configured for debugging Rust. A # `debug`-enabled compiler and standard library will be somewhat @@ -540,7 +543,7 @@ # "maximally debuggable" environment (notably libstd) takes # hours to build. # -#debug = false +#rust.debug = false # Whether to download the stage 1 and 2 compilers from CI. This is useful if you # are working on tools, doc-comments, or library (you will be able to build the @@ -553,37 +556,37 @@ # # Set this to `true` to always download or `false` to always use the in-tree # compiler. -#download-rustc = false +#rust.download-rustc = false # Number of codegen units to use for each compiler invocation. A value of 0 # means "the number of cores on this machine", and 1+ is passed through to the # compiler. # # Uses the rustc defaults: https://doc.rust-lang.org/rustc/codegen-options/index.html#codegen-units -#codegen-units = if incremental { 256 } else { 16 } +#rust.codegen-units = if incremental { 256 } else { 16 } # Sets the number of codegen units to build the standard library with, # regardless of what the codegen-unit setting for the rest of the compiler is. # NOTE: building with anything other than 1 is known to occasionally have bugs. -#codegen-units-std = codegen-units +#rust.codegen-units-std = codegen-units # Whether or not debug assertions are enabled for the compiler and standard library. # These can help find bugs at the cost of a small runtime slowdown. # # Defaults to rust.debug value -#debug-assertions = rust.debug (boolean) +#rust.debug-assertions = rust.debug (boolean) # Whether or not debug assertions are enabled for the standard library. # Overrides the `debug-assertions` option, if defined. # # Defaults to rust.debug-assertions value -#debug-assertions-std = rust.debug-assertions (boolean) +#rust.debug-assertions-std = rust.debug-assertions (boolean) # Whether or not debug assertions are enabled for the tools built by bootstrap. # Overrides the `debug-assertions` option, if defined. # # Defaults to rust.debug-assertions value -#debug-assertions-tools = rust.debug-assertions (boolean) +#rust.debug-assertions-tools = rust.debug-assertions (boolean) # Whether or not to leave debug! and trace! calls in the rust binary. # @@ -591,22 +594,22 @@ # # If you see a message from `tracing` saying "some trace filter directives would enable traces that # are disabled statically" because `max_level_info` is enabled, set this value to `true`. -#debug-logging = rust.debug-assertions (boolean) +#rust.debug-logging = rust.debug-assertions (boolean) # Whether or not to build rustc, tools and the libraries with randomized type layout -#randomize-layout = false +#rust.randomize-layout = false # Whether or not overflow checks are enabled for the compiler and standard # library. # # Defaults to rust.debug value -#overflow-checks = rust.debug (boolean) +#rust.overflow-checks = rust.debug (boolean) # Whether or not overflow checks are enabled for the standard library. # Overrides the `overflow-checks` option, if defined. # # Defaults to rust.overflow-checks value -#overflow-checks-std = rust.overflow-checks (boolean) +#rust.overflow-checks-std = rust.overflow-checks (boolean) # Debuginfo level for most of Rust code, corresponds to the `-C debuginfo=N` option of `rustc`. # See https://doc.rust-lang.org/rustc/codegen-options/index.html#debuginfo for available options. @@ -617,20 +620,20 @@ # # Note that debuginfo-level = 2 generates several gigabytes of debuginfo # and will slow down the linking process significantly. -#debuginfo-level = if rust.debug { 1 } else { 0 } +#rust.debuginfo-level = if rust.debug { 1 } else { 0 } # Debuginfo level for the compiler. -#debuginfo-level-rustc = rust.debuginfo-level +#rust.debuginfo-level-rustc = rust.debuginfo-level # Debuginfo level for the standard library. -#debuginfo-level-std = rust.debuginfo-level +#rust.debuginfo-level-std = rust.debuginfo-level # Debuginfo level for the tools. -#debuginfo-level-tools = rust.debuginfo-level +#rust.debuginfo-level-tools = rust.debuginfo-level # Debuginfo level for the test suites run with compiletest. # FIXME(#61117): Some tests fail when this option is enabled. -#debuginfo-level-tests = 0 +#rust.debuginfo-level-tests = 0 # Should rustc and the standard library be built with split debuginfo? Default # is platform dependent. @@ -640,13 +643,13 @@ # The value specified here is only used when targeting the `build.build` triple, # and is overridden by `target..split-debuginfo` if specified. # -#split-debuginfo = see target..split-debuginfo +#rust.split-debuginfo = see target..split-debuginfo # Whether or not `panic!`s generate backtraces (RUST_BACKTRACE) -#backtrace = true +#rust.backtrace = true # Whether to always use incremental compilation when building rustc -#incremental = false +#rust.incremental = false # The default linker that will be hard-coded into the generated # compiler for targets that don't specify a default linker explicitly @@ -656,7 +659,7 @@ # setting. # # See https://doc.rust-lang.org/rustc/codegen-options/index.html#linker for more information. -#default-linker = (path) +#rust.default-linker = (path) # The "channel" for the Rust build to produce. The stable/beta channels only # allow using stable features, whereas the nightly and dev channels allow using @@ -665,7 +668,7 @@ # You can set the channel to "auto-detect" to load the channel name from `src/ci/channel`. # # If using tarball sources, default value is "auto-detect", otherwise, it's "dev". -#channel = if "is a tarball source" { "auto-detect" } else { "dev" } +#rust.channel = if "is a tarball source" { "auto-detect" } else { "dev" } # The root location of the musl installation directory. The library directory # will also need to contain libunwind.a for an unwinding implementation. Note @@ -673,65 +676,65 @@ # linked binaries. # # Defaults to /usr on musl hosts. Has no default otherwise. -#musl-root = (path) +#rust.musl-root = (path) # By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix # platforms to ensure that the compiler is usable by default from the build # directory (as it links to a number of dynamic libraries). This may not be # desired in distributions, for example. -#rpath = true +#rust.rpath = true # Indicates whether symbols should be stripped using `-Cstrip=symbols`. -#strip = false +#rust.strip = false # Forces frame pointers to be used with `-Cforce-frame-pointers`. # This can be helpful for profiling at a small performance cost. -#frame-pointers = false +#rust.frame-pointers = false # Indicates whether stack protectors should be used # via the unstable option `-Zstack-protector`. # # Valid options are : `none`(default),`basic`,`strong`, or `all`. # `strong` and `basic` options may be buggy and are not recommended, see rust-lang/rust#114903. -#stack-protector = "none" +#rust.stack-protector = "none" # Prints each test name as it is executed, to help debug issues in the test harness itself. -#verbose-tests = if is_verbose { true } else { false } +#rust.verbose-tests = if is_verbose { true } else { false } # Flag indicating whether tests are compiled with optimizations (the -O flag). -#optimize-tests = true +#rust.optimize-tests = true # Flag indicating whether codegen tests will be run or not. If you get an error # saying that the FileCheck executable is missing, you may want to disable this. # Also see the target's llvm-filecheck option. -#codegen-tests = true +#rust.codegen-tests = true # Flag indicating whether git info will be retrieved from .git automatically. # Having the git information can cause a lot of rebuilds during development. -#omit-git-hash = if rust.channel == "dev" { true } else { false } +#rust.omit-git-hash = if rust.channel == "dev" { true } else { false } # Whether to create a source tarball by default when running `x dist`. # # You can still build a source tarball when this is disabled by explicitly passing `x dist rustc-src`. -#dist-src = true +#rust.dist-src = true # After building or testing an optional component (e.g. the nomicon or reference), append the # result (broken, compiling, testing) into this JSON file. -#save-toolstates = (path) +#rust.save-toolstates = (path) # This is an array of the codegen backends that will be compiled for the rustc # that's being compiled. The default is to only build the LLVM codegen backend, # and currently the only standard options supported are `"llvm"`, `"cranelift"` # and `"gcc"`. The first backend in this list will be used as default by rustc # when no explicit backend is specified. -#codegen-backends = ["llvm"] +#rust.codegen-backends = ["llvm"] # Indicates whether LLD will be compiled and made available in the sysroot for rustc to execute, and # whether to set it as rustc's default linker on `x86_64-unknown-linux-gnu`. This will also only be # when *not* building an external LLVM (so only when using `download-ci-llvm` or building LLVM from # the in-tree source): setting `llvm-config` in the `[target.x86_64-unknown-linux-gnu]` section will # make this default to false. -#lld = false in all cases, except on `x86_64-unknown-linux-gnu` as described above, where it is true +#rust.lld = false in all cases, except on `x86_64-unknown-linux-gnu` as described above, where it is true # Indicates whether LLD will be used to link Rust crates during bootstrap on # supported platforms. @@ -742,56 +745,56 @@ # On MSVC, LLD will not be used if we're cross linking. # # Explicitly setting the linker for a target will override this option when targeting MSVC. -#use-lld = false +#rust.use-lld = false # Indicates whether some LLVM tools, like llvm-objdump, will be made available in the # sysroot. -#llvm-tools = true +#rust.llvm-tools = true # Indicates whether the `self-contained` llvm-bitcode-linker, will be made available # in the sysroot. It is required for running nvptx tests. -#llvm-bitcode-linker = false +#rust.llvm-bitcode-linker = false # Whether to deny warnings in crates -#deny-warnings = true +#rust.deny-warnings = true # Print backtrace on internal compiler errors during bootstrap -#backtrace-on-ice = false +#rust.backtrace-on-ice = false # Whether to verify generated LLVM IR -#verify-llvm-ir = false +#rust.verify-llvm-ir = false # Compile the compiler with a non-default ThinLTO import limit. This import # limit controls the maximum size of functions imported by ThinLTO. Decreasing # will make code compile faster at the expense of lower runtime performance. -#thin-lto-import-instr-limit = if incremental { 10 } else { LLVM default (currently 100) } +#rust.thin-lto-import-instr-limit = if incremental { 10 } else { LLVM default (currently 100) } # Map debuginfo paths to `/rust/$sha/...`. # Useful for reproducible builds. Generally only set for releases -#remap-debuginfo = false +#rust.remap-debuginfo = false # Link the compiler and LLVM against `jemalloc` instead of the default libc allocator. # This option is only tested on Linux and OSX. It can also be configured per-target in the # [target.] section. -#jemalloc = false +#rust.jemalloc = false # Run tests in various test suites with the "nll compare mode" in addition to # running the tests in normal mode. Largely only used on CI and during local # development of NLL -#test-compare-mode = false +#rust.test-compare-mode = false # Global default for llvm-libunwind for all targets. See the target-specific # documentation for llvm-libunwind below. Note that the target-specific # option will override this if set. -#llvm-libunwind = 'no' +#rust.llvm-libunwind = 'no' # Enable Windows Control Flow Guard checks in the standard library. # This only applies from stage 1 onwards, and only for Windows targets. -#control-flow-guard = false +#rust.control-flow-guard = false # Enable Windows EHCont Guard checks in the standard library. # This only applies from stage 1 onwards, and only for Windows targets. -#ehcont-guard = false +#rust.ehcont-guard = false # Enable symbol-mangling-version v0. This can be helpful when profiling rustc, # as generics will be preserved in symbols (rather than erased into opaque T). @@ -799,16 +802,16 @@ # compiler and its tools and the legacy scheme will be used when compiling the # standard library. # If an explicit setting is given, it will be used for all parts of the codebase. -#new-symbol-mangling = true|false (see comment) +#rust.new-symbol-mangling = true|false (see comment) # Select LTO mode that will be used for compiling rustc. By default, thin local LTO # (LTO within a single crate) is used (like for any Rust crate). You can also select # "thin" or "fat" to apply Thin/Fat LTO to the `rustc_driver` dylib, or "off" to disable # LTO entirely. -#lto = "thin-local" +#rust.lto = "thin-local" # Build compiler with the optimization enabled and -Zvalidate-mir, currently only for `std` -#validate-mir-opts = 3 +#rust.validate-mir-opts = 3 # Configure `std` features used during bootstrap. # @@ -822,7 +825,57 @@ # # Since libstd also builds libcore and liballoc as dependencies and all their features are mirrored # as libstd features, this option can also be used to configure features such as optimize_for_size. -#std-features = ["panic_unwind"] +#rust.std-features = ["panic_unwind"] + +# ============================================================================= +# Distribution options +# +# These options are related to distribution, mostly for the Rust project itself. +# You probably won't need to concern yourself with any of these options +# ============================================================================= + +# This is the folder of artifacts that the build system will sign. All files in +# this directory will be signed with the default gpg key using the system `gpg` +# binary. The `asc` and `sha256` files will all be output into the standard dist +# output folder (currently `build/dist`) +# +# This folder should be populated ahead of time before the build system is +# invoked. +#dist.sign-folder = (path) + +# The remote address that all artifacts will eventually be uploaded to. The +# build system generates manifests which will point to these urls, and for the +# manifests to be correct they'll have to have the right URLs encoded. +# +# Note that this address should not contain a trailing slash as file names will +# be appended to it. +#dist.upload-addr = (URL) + +# Whether to build a plain source tarball to upload +# We disable that on Windows not to override the one already uploaded on S3 +# as the one built on Windows will contain backslashes in paths causing problems +# on linux +#dist.src-tarball = true + +# List of compression formats to use when generating dist tarballs. The list of +# formats is provided to rust-installer, which must support all of them. +# +# This list must be non-empty. +#dist.compression-formats = ["gz", "xz"] + +# How much time should be spent compressing the tarballs. The better the +# compression profile, the longer compression will take. +# +# Available options: fast, balanced, best +#dist.compression-profile = "fast" + +# Copy the linker, DLLs, and various libraries from MinGW into the Rust toolchain. +# Only applies when the host or target is pc-windows-gnu. +#dist.include-mingw-linker = true + +# Whether to vendor dependencies for the dist tarball. +#dist.vendor = if "is a tarball source" || "is a git repository" { true } else { false } + # ============================================================================= # Options for specific targets @@ -973,53 +1026,3 @@ # Link the compiler and LLVM against `jemalloc` instead of the default libc allocator. # This overrides the global `rust.jemalloc` option. See that option for more info. #jemalloc = rust.jemalloc (bool) - -# ============================================================================= -# Distribution options -# -# These options are related to distribution, mostly for the Rust project itself. -# You probably won't need to concern yourself with any of these options -# ============================================================================= -[dist] - -# This is the folder of artifacts that the build system will sign. All files in -# this directory will be signed with the default gpg key using the system `gpg` -# binary. The `asc` and `sha256` files will all be output into the standard dist -# output folder (currently `build/dist`) -# -# This folder should be populated ahead of time before the build system is -# invoked. -#sign-folder = (path) - -# The remote address that all artifacts will eventually be uploaded to. The -# build system generates manifests which will point to these urls, and for the -# manifests to be correct they'll have to have the right URLs encoded. -# -# Note that this address should not contain a trailing slash as file names will -# be appended to it. -#upload-addr = (URL) - -# Whether to build a plain source tarball to upload -# We disable that on Windows not to override the one already uploaded on S3 -# as the one built on Windows will contain backslashes in paths causing problems -# on linux -#src-tarball = true - -# List of compression formats to use when generating dist tarballs. The list of -# formats is provided to rust-installer, which must support all of them. -# -# This list must be non-empty. -#compression-formats = ["gz", "xz"] - -# How much time should be spent compressing the tarballs. The better the -# compression profile, the longer compression will take. -# -# Available options: fast, balanced, best -#compression-profile = "fast" - -# Copy the linker, DLLs, and various libraries from MinGW into the Rust toolchain. -# Only applies when the host or target is pc-windows-gnu. -#include-mingw-linker = true - -# Whether to vendor dependencies for the dist tarball. -#vendor = if "is a tarball source" || "is a git repository" { true } else { false } diff --git a/compiler/rustc_abi/src/canon_abi.rs b/compiler/rustc_abi/src/canon_abi.rs index 7c020be67617..13f9a04b286f 100644 --- a/compiler/rustc_abi/src/canon_abi.rs +++ b/compiler/rustc_abi/src/canon_abi.rs @@ -63,8 +63,8 @@ impl fmt::Display for CanonAbi { CanonAbi::Custom => ExternAbi::Custom, CanonAbi::Arm(arm_call) => match arm_call { ArmCall::Aapcs => ExternAbi::Aapcs { unwind: false }, - ArmCall::CCmseNonSecureCall => ExternAbi::CCmseNonSecureCall, - ArmCall::CCmseNonSecureEntry => ExternAbi::CCmseNonSecureEntry, + ArmCall::CCmseNonSecureCall => ExternAbi::CmseNonSecureCall, + ArmCall::CCmseNonSecureEntry => ExternAbi::CmseNonSecureEntry, }, CanonAbi::GpuKernel => ExternAbi::GpuKernel, CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind { diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs index 7457ae1f0334..29a3678abf3f 100644 --- a/compiler/rustc_abi/src/extern_abi.rs +++ b/compiler/rustc_abi/src/extern_abi.rs @@ -36,6 +36,10 @@ pub enum ExternAbi { /// Stronger than just `#[cold]` because `fn` pointers might be incompatible. RustCold, + /// An always-invalid ABI that's used to test "this ABI is not supported by this platform" + /// in a platform-agnostic way. + RustInvalid, + /// Unstable impl detail that directly uses Rust types to describe the ABI to LLVM. /// Even normally-compatible Rust types can become ABI-incompatible with this ABI! Unadjusted, @@ -55,9 +59,9 @@ pub enum ExternAbi { unwind: bool, }, /// extremely constrained barely-C ABI for TrustZone - CCmseNonSecureCall, + CmseNonSecureCall, /// extremely constrained barely-C ABI for TrustZone - CCmseNonSecureEntry, + CmseNonSecureEntry, /* gpu */ /// An entry-point function called by the GPU's host @@ -136,8 +140,6 @@ macro_rules! abi_impls { abi_impls! { ExternAbi = { C { unwind: false } =><= "C", - CCmseNonSecureCall =><= "C-cmse-nonsecure-call", - CCmseNonSecureEntry =><= "C-cmse-nonsecure-entry", C { unwind: true } =><= "C-unwind", Rust =><= "Rust", Aapcs { unwind: false } =><= "aapcs", @@ -146,6 +148,8 @@ abi_impls! { AvrNonBlockingInterrupt =><= "avr-non-blocking-interrupt", Cdecl { unwind: false } =><= "cdecl", Cdecl { unwind: true } =><= "cdecl-unwind", + CmseNonSecureCall =><= "cmse-nonsecure-call", + CmseNonSecureEntry =><= "cmse-nonsecure-entry", Custom =><= "custom", EfiApi =><= "efiapi", Fastcall { unwind: false } =><= "fastcall", @@ -157,6 +161,7 @@ abi_impls! { RiscvInterruptS =><= "riscv-interrupt-s", RustCall =><= "rust-call", RustCold =><= "rust-cold", + RustInvalid =><= "rust-invalid", Stdcall { unwind: false } =><= "stdcall", Stdcall { unwind: true } =><= "stdcall-unwind", System { unwind: false } =><= "system", diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 58a7fcae9f64..80b44e432eeb 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -432,7 +432,7 @@ impl LayoutCalculator { align = align.min(AbiAlign::new(pack)); } // The unadjusted ABI alignment does not include repr(align), but does include repr(pack). - // See documentation on `LayoutS::unadjusted_abi_align`. + // See documentation on `LayoutData::unadjusted_abi_align`. let unadjusted_abi_align = align.abi; if let Some(repr_align) = repr.align { align = align.max(AbiAlign::new(repr_align)); @@ -602,10 +602,10 @@ impl LayoutCalculator { dont_niche_optimize_enum: bool, ) -> LayoutCalculatorResult { // Until we've decided whether to use the tagged or - // niche filling LayoutS, we don't want to intern the + // niche filling LayoutData, we don't want to intern the // variant layouts, so we can't store them in the - // overall LayoutS. Store the overall LayoutS - // and the variant LayoutSs here until then. + // overall LayoutData. Store the overall LayoutData + // and the variant LayoutDatas here until then. struct TmpLayout { layout: LayoutData, variants: IndexVec>, @@ -1214,7 +1214,7 @@ impl LayoutCalculator { match kind { StructKind::AlwaysSized | StructKind::MaybeUnsized => { - // Currently `LayoutS` only exposes a single niche so sorting is usually + // Currently `LayoutData` only exposes a single niche so sorting is usually // sufficient to get one niche into the preferred position. If it ever // supported multiple niches then a more advanced pick-and-pack approach could // provide better results. But even for the single-niche cache it's not @@ -1333,7 +1333,7 @@ impl LayoutCalculator { } // The unadjusted ABI alignment does not include repr(align), but does include repr(pack). - // See documentation on `LayoutS::unadjusted_abi_align`. + // See documentation on `LayoutData::unadjusted_abi_align`. let unadjusted_abi_align = align.abi; if let Some(repr_align) = repr.align { align = align.max(AbiAlign::new(repr_align)); diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index bb880a58e527..18f0750aaa1f 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -71,7 +71,7 @@ pub struct Layout<'a>(pub Interned<'a, LayoutData>); impl<'a> fmt::Debug for Layout<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // See comment on `::fmt` above. + // See comment on `::fmt` above. self.0.0.fmt(f) } } diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 4268e68b2e42..6d729b6919a7 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1785,7 +1785,7 @@ where { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // This is how `Layout` used to print before it become - // `Interned`. We print it like this to avoid having to update + // `Interned`. We print it like this to avoid having to update // expected output in a lot of tests. let LayoutData { size, diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index b2d3b90fc449..5de2e69072fa 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -7,7 +7,7 @@ edition = "2024" # tidy-alphabetical-start bitflags = "2.4.1" memchr = "2.7.4" -rustc-literal-escaper = "0.0.2" +rustc-literal-escaper = "0.0.4" rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 11afd359e5ad..ab8dac160266 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -904,6 +904,10 @@ pub enum BorrowKind { /// The resulting type is either `*const T` or `*mut T` /// where `T = typeof($expr)`. Raw, + /// A pinned borrow, `&pin const $expr` or `&pin mut $expr`. + /// The resulting type is either `Pin<&'a T>` or `Pin<&'a mut T>` + /// where `T = typeof($expr)` and `'a` is some lifetime. + Pin, } #[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)] diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 797ab297319b..9d91f41d6c79 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -321,6 +321,13 @@ impl AstNodeWrapper { } } +// FIXME: remove after `stmt_expr_attributes` is stabilized. +impl From, Tag>> for AstNodeWrapper { + fn from(value: AstNodeWrapper, Tag>) -> Self { + AstNodeWrapper { wrapped: *value.wrapped, tag: value.tag } + } +} + impl HasNodeId for AstNodeWrapper { fn node_id(&self) -> NodeId { self.wrapped.node_id() diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 621e3042b62e..44865c493b3b 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -206,12 +206,24 @@ impl AttributeExt for Attribute { } } - fn style(&self) -> AttrStyle { - self.style + fn doc_resolution_scope(&self) -> Option { + match &self.kind { + AttrKind::DocComment(..) => Some(self.style), + AttrKind::Normal(normal) + if normal.item.path == sym::doc && normal.item.value_str().is_some() => + { + Some(self.style) + } + _ => None, + } } } impl Attribute { + pub fn style(&self) -> AttrStyle { + self.style + } + pub fn may_have_doc_links(&self) -> bool { self.doc_str().is_some_and(|s| comments::may_have_doc_links(s.as_str())) } @@ -806,7 +818,14 @@ pub trait AttributeExt: Debug { /// * `#[doc(...)]` returns `None`. fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)>; - fn style(&self) -> AttrStyle; + /// Returns outer or inner if this is a doc attribute or a sugared doc + /// comment, otherwise None. + /// + /// This is used in the case of doc comments on modules, to decide whether + /// to resolve intra-doc links against the symbols in scope within the + /// commented module (for inner doc) vs within its parent module (for outer + /// doc). + fn doc_resolution_scope(&self) -> Option; } // FIXME(fn_delegation): use function delegation instead of manually forwarding @@ -881,8 +900,4 @@ impl Attribute { pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> { AttributeExt::doc_str_and_comment_kind(self) } - - pub fn style(&self) -> AttrStyle { - AttributeExt::style(self) - } } diff --git a/compiler/rustc_ast/src/format.rs b/compiler/rustc_ast/src/format.rs index b611ddea1d9f..28d260419c51 100644 --- a/compiler/rustc_ast/src/format.rs +++ b/compiler/rustc_ast/src/format.rs @@ -50,6 +50,14 @@ pub struct FormatArgs { /// /// Generally only useful for lints that care about the raw bytes the user wrote. pub uncooked_fmt_str: (LitKind, Symbol), + /// Was the format literal written in the source? + /// - `format!("boo")` => true, + /// - `format!(concat!("b", "o", "o"))` => false, + /// - `format!(include_str!("boo.txt"))` => false, + /// + /// If it wasn't written in the source then we have to be careful with spans pointing into it + /// and suggestions about rewriting it. + pub is_source_literal: bool, } /// A piece of a format template string. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 07fbe8045fc2..3eae19f4daa1 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -13,7 +13,7 @@ use std::panic; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_span::source_map::Spanned; use rustc_span::{Ident, Span}; -use smallvec::{Array, SmallVec, smallvec}; +use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; use crate::ast::*; @@ -21,17 +21,6 @@ use crate::ptr::P; use crate::tokenstream::*; use crate::visit::{AssocCtxt, BoundKind, FnCtxt, VisitorResult, try_visit, visit_opt, walk_list}; -pub trait ExpectOne { - fn expect_one(self, err: &'static str) -> A::Item; -} - -impl ExpectOne for SmallVec { - fn expect_one(self, err: &'static str) -> A::Item { - assert!(self.len() == 1, "{}", err); - self.into_iter().next().unwrap() - } -} - mod sealed { use rustc_ast_ir::visit::VisitorResult; @@ -47,323 +36,6 @@ mod sealed { use sealed::MutVisitorResult; -pub trait MutVisitor: Sized + MutVisitorResult { - // Methods in this trait have one of three forms: - // - // fn visit_t(&mut self, t: &mut T); // common - // fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>; // rare - // fn filter_map_t(&mut self, t: T) -> Option; // rarest - // - // When writing these methods, it is better to use destructuring like this: - // - // fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) { - // visit_a(a); - // visit_b(b); - // } - // - // than to use field access like this: - // - // fn visit_abc(&mut self, abc: &mut ABC) { - // visit_a(&mut abc.a); - // visit_b(&mut abc.b); - // // ignore abc.c - // } - // - // As well as being more concise, the former is explicit about which fields - // are skipped. Furthermore, if a new field is added, the destructuring - // version will cause a compile error, which is good. In comparison, the - // field access version will continue working and it would be easy to - // forget to add handling for it. - - fn visit_crate(&mut self, c: &mut Crate) { - walk_crate(self, c) - } - - fn visit_meta_list_item(&mut self, list_item: &mut MetaItemInner) { - walk_meta_list_item(self, list_item); - } - - fn visit_meta_item(&mut self, meta_item: &mut MetaItem) { - walk_meta_item(self, meta_item); - } - - fn visit_use_tree(&mut self, use_tree: &mut UseTree) { - walk_use_tree(self, use_tree); - } - - fn visit_foreign_item(&mut self, ni: &mut ForeignItem) { - walk_item(self, ni); - } - - fn flat_map_foreign_item(&mut self, ni: P) -> SmallVec<[P; 1]> { - walk_flat_map_foreign_item(self, ni) - } - - fn visit_item(&mut self, i: &mut Item) { - walk_item(self, i); - } - - fn flat_map_item(&mut self, i: P) -> SmallVec<[P; 1]> { - walk_flat_map_item(self, i) - } - - fn visit_fn_header(&mut self, header: &mut FnHeader) { - walk_fn_header(self, header); - } - - fn visit_field_def(&mut self, fd: &mut FieldDef) { - walk_field_def(self, fd); - } - - fn flat_map_field_def(&mut self, fd: FieldDef) -> SmallVec<[FieldDef; 1]> { - walk_flat_map_field_def(self, fd) - } - - fn visit_assoc_item(&mut self, i: &mut AssocItem, ctxt: AssocCtxt) { - walk_assoc_item(self, i, ctxt) - } - - fn flat_map_assoc_item( - &mut self, - i: P, - ctxt: AssocCtxt, - ) -> SmallVec<[P; 1]> { - walk_flat_map_assoc_item(self, i, ctxt) - } - - fn visit_contract(&mut self, c: &mut FnContract) { - walk_contract(self, c); - } - - fn visit_fn_decl(&mut self, d: &mut FnDecl) { - walk_fn_decl(self, d); - } - - /// `Span` and `NodeId` are mutated at the caller site. - fn visit_fn(&mut self, fk: FnKind<'_>, _: Span, _: NodeId) { - walk_fn(self, fk) - } - - fn visit_coroutine_kind(&mut self, a: &mut CoroutineKind) { - walk_coroutine_kind(self, a); - } - - fn visit_closure_binder(&mut self, b: &mut ClosureBinder) { - walk_closure_binder(self, b); - } - - fn visit_block(&mut self, b: &mut Block) { - walk_block(self, b); - } - - fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> { - walk_flat_map_stmt(self, s) - } - - fn visit_arm(&mut self, arm: &mut Arm) { - walk_arm(self, arm); - } - - fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> { - walk_flat_map_arm(self, arm) - } - - fn visit_pat(&mut self, p: &mut Pat) { - walk_pat(self, p); - } - - fn visit_anon_const(&mut self, c: &mut AnonConst) { - walk_anon_const(self, c); - } - - fn visit_expr(&mut self, e: &mut Expr) { - walk_expr(self, e); - } - - /// This method is a hack to workaround unstable of `stmt_expr_attributes`. - /// It can be removed once that feature is stabilized. - fn visit_method_receiver_expr(&mut self, ex: &mut P) { - self.visit_expr(ex) - } - - fn filter_map_expr(&mut self, e: P) -> Option> { - walk_filter_map_expr(self, e) - } - - fn visit_generic_arg(&mut self, arg: &mut GenericArg) { - walk_generic_arg(self, arg); - } - - fn visit_ty(&mut self, t: &mut Ty) { - walk_ty(self, t); - } - - fn visit_ty_pat(&mut self, t: &mut TyPat) { - walk_ty_pat(self, t); - } - - fn visit_lifetime(&mut self, l: &mut Lifetime) { - walk_lifetime(self, l); - } - - fn visit_assoc_item_constraint(&mut self, c: &mut AssocItemConstraint) { - walk_assoc_item_constraint(self, c); - } - - fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) { - walk_foreign_mod(self, nm); - } - - fn visit_variant(&mut self, v: &mut Variant) { - walk_variant(self, v); - } - - fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> { - walk_flat_map_variant(self, v) - } - - fn visit_ident(&mut self, i: &mut Ident) { - self.visit_span(&mut i.span); - } - - fn visit_path(&mut self, p: &mut Path) { - walk_path(self, p); - } - - fn visit_path_segment(&mut self, p: &mut PathSegment) { - walk_path_segment(self, p) - } - - fn visit_qself(&mut self, qs: &mut Option>) { - walk_qself(self, qs); - } - - fn visit_generic_args(&mut self, p: &mut GenericArgs) { - walk_generic_args(self, p); - } - - fn visit_local(&mut self, l: &mut Local) { - walk_local(self, l); - } - - fn visit_mac_call(&mut self, mac: &mut MacCall) { - walk_mac(self, mac); - } - - fn visit_macro_def(&mut self, def: &mut MacroDef) { - walk_macro_def(self, def); - } - - fn visit_label(&mut self, label: &mut Label) { - walk_label(self, label); - } - - fn visit_attribute(&mut self, at: &mut Attribute) { - walk_attribute(self, at); - } - - fn visit_param(&mut self, param: &mut Param) { - walk_param(self, param); - } - - fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> { - walk_flat_map_param(self, param) - } - - fn visit_generics(&mut self, generics: &mut Generics) { - walk_generics(self, generics); - } - - fn visit_trait_ref(&mut self, tr: &mut TraitRef) { - walk_trait_ref(self, tr); - } - - fn visit_poly_trait_ref(&mut self, p: &mut PolyTraitRef) { - walk_poly_trait_ref(self, p); - } - - fn visit_variant_data(&mut self, vdata: &mut VariantData) { - walk_variant_data(self, vdata); - } - - fn visit_generic_param(&mut self, param: &mut GenericParam) { - walk_generic_param(self, param) - } - - fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> { - walk_flat_map_generic_param(self, param) - } - - fn visit_param_bound(&mut self, tpb: &mut GenericBound, _ctxt: BoundKind) { - walk_param_bound(self, tpb); - } - - fn visit_precise_capturing_arg(&mut self, arg: &mut PreciseCapturingArg) { - walk_precise_capturing_arg(self, arg); - } - - fn visit_expr_field(&mut self, f: &mut ExprField) { - walk_expr_field(self, f); - } - - fn flat_map_expr_field(&mut self, f: ExprField) -> SmallVec<[ExprField; 1]> { - walk_flat_map_expr_field(self, f) - } - - fn flat_map_where_predicate( - &mut self, - where_predicate: WherePredicate, - ) -> SmallVec<[WherePredicate; 1]> { - walk_flat_map_where_predicate(self, where_predicate) - } - - fn visit_where_predicate_kind(&mut self, kind: &mut WherePredicateKind) { - walk_where_predicate_kind(self, kind) - } - - fn visit_vis(&mut self, vis: &mut Visibility) { - walk_vis(self, vis); - } - - fn visit_id(&mut self, _id: &mut NodeId) { - // Do nothing. - } - - // Span visiting is no longer used, but we keep it for now, - // in case it's needed for something like #127241. - fn visit_span(&mut self, _sp: &mut Span) { - // Do nothing. - } - - fn visit_pat_field(&mut self, fp: &mut PatField) { - walk_pat_field(self, fp) - } - - fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> { - walk_flat_map_pat_field(self, fp) - } - - fn visit_inline_asm(&mut self, asm: &mut InlineAsm) { - walk_inline_asm(self, asm) - } - - fn visit_inline_asm_sym(&mut self, sym: &mut InlineAsmSym) { - walk_inline_asm_sym(self, sym) - } - - fn visit_format_args(&mut self, fmt: &mut FormatArgs) { - walk_format_args(self, fmt) - } - - fn visit_capture_by(&mut self, capture_by: &mut CaptureBy) { - walk_capture_by(self, capture_by) - } - - fn visit_fn_ret_ty(&mut self, fn_ret_ty: &mut FnRetTy) { - walk_fn_ret_ty(self, fn_ret_ty) - } -} - super::common_visitor_and_walkers!((mut) MutVisitor); macro_rules! generate_flat_map_visitor_fns { @@ -398,22 +70,6 @@ generate_flat_map_visitor_fns! { visit_arms, Arm, flat_map_arm; } -#[inline] -fn visit_thin_vec(elems: &mut ThinVec, mut visit_elem: F) -where - F: FnMut(&mut T), -{ - for elem in elems { - visit_elem(elem); - } -} - -fn visit_attrs(vis: &mut T, attrs: &mut AttrVec) { - for attr in attrs.iter_mut() { - vis.visit_attribute(attr); - } -} - pub fn walk_flat_map_pat_field( vis: &mut T, mut fp: PatField, @@ -431,47 +87,26 @@ fn visit_nested_use_tree( vis.visit_use_tree(nested_tree); } -pub fn walk_flat_map_arm(vis: &mut T, mut arm: Arm) -> SmallVec<[Arm; 1]> { - vis.visit_arm(&mut arm); - smallvec![arm] +macro_rules! generate_walk_flat_map_fns { + ($($fn_name:ident($Ty:ty$(,$extra_name:ident: $ExtraTy:ty)*) => $visit_fn_name:ident;)+) => {$( + pub fn $fn_name(vis: &mut V, mut value: $Ty$(,$extra_name: $ExtraTy)*) -> SmallVec<[$Ty; 1]> { + vis.$visit_fn_name(&mut value$(,$extra_name)*); + smallvec![value] + } + )+}; } -pub fn walk_flat_map_variant( - vis: &mut T, - mut variant: Variant, -) -> SmallVec<[Variant; 1]> { - vis.visit_variant(&mut variant); - smallvec![variant] -} - -fn walk_meta_list_item(vis: &mut T, li: &mut MetaItemInner) { - match li { - MetaItemInner::MetaItem(mi) => vis.visit_meta_item(mi), - MetaItemInner::Lit(_lit) => {} - } -} - -fn walk_meta_item(vis: &mut T, mi: &mut MetaItem) { - let MetaItem { unsafety: _, path: _, kind, span } = mi; - match kind { - MetaItemKind::Word => {} - MetaItemKind::List(mis) => visit_thin_vec(mis, |mi| vis.visit_meta_list_item(mi)), - MetaItemKind::NameValue(_s) => {} - } - vis.visit_span(span); -} - -pub fn walk_flat_map_param(vis: &mut T, mut param: Param) -> SmallVec<[Param; 1]> { - vis.visit_param(&mut param); - smallvec![param] -} - -pub fn walk_flat_map_generic_param( - vis: &mut T, - mut param: GenericParam, -) -> SmallVec<[GenericParam; 1]> { - vis.visit_generic_param(&mut param); - smallvec![param] +generate_walk_flat_map_fns! { + walk_flat_map_arm(Arm) => visit_arm; + walk_flat_map_variant(Variant) => visit_variant; + walk_flat_map_param(Param) => visit_param; + walk_flat_map_generic_param(GenericParam) => visit_generic_param; + walk_flat_map_where_predicate(WherePredicate) => visit_where_predicate; + walk_flat_map_field_def(FieldDef) => visit_field_def; + walk_flat_map_expr_field(ExprField) => visit_expr_field; + walk_flat_map_item(P) => visit_item; + walk_flat_map_foreign_item(P) => visit_foreign_item; + walk_flat_map_assoc_item(P, ctxt: AssocCtxt) => visit_assoc_item; } fn walk_ty_alias_where_clauses(vis: &mut T, tawcs: &mut TyAliasWhereClauses) { @@ -482,63 +117,6 @@ fn walk_ty_alias_where_clauses(vis: &mut T, tawcs: &mut TyAliasWh vis.visit_span(span_after); } -pub fn walk_flat_map_where_predicate( - vis: &mut T, - mut pred: WherePredicate, -) -> SmallVec<[WherePredicate; 1]> { - walk_where_predicate(vis, &mut pred); - smallvec![pred] -} - -pub fn walk_flat_map_field_def( - vis: &mut T, - mut fd: FieldDef, -) -> SmallVec<[FieldDef; 1]> { - vis.visit_field_def(&mut fd); - smallvec![fd] -} - -pub fn walk_flat_map_expr_field( - vis: &mut T, - mut f: ExprField, -) -> SmallVec<[ExprField; 1]> { - vis.visit_expr_field(&mut f); - smallvec![f] -} - -pub fn walk_item_kind( - kind: &mut K, - span: Span, - id: NodeId, - visibility: &mut Visibility, - ctxt: K::Ctxt, - vis: &mut impl MutVisitor, -) { - kind.walk(span, id, visibility, ctxt, vis) -} - -pub fn walk_flat_map_item(vis: &mut impl MutVisitor, mut item: P) -> SmallVec<[P; 1]> { - vis.visit_item(&mut item); - smallvec![item] -} - -pub fn walk_flat_map_foreign_item( - vis: &mut impl MutVisitor, - mut item: P, -) -> SmallVec<[P; 1]> { - vis.visit_foreign_item(&mut item); - smallvec![item] -} - -pub fn walk_flat_map_assoc_item( - vis: &mut impl MutVisitor, - mut item: P, - ctxt: AssocCtxt, -) -> SmallVec<[P; 1]> { - vis.visit_assoc_item(&mut item, ctxt); - smallvec![item] -} - pub fn walk_filter_map_expr(vis: &mut T, mut e: P) -> Option> { vis.visit_expr(&mut e); Some(e) @@ -576,35 +154,11 @@ fn walk_flat_map_stmt_kind(vis: &mut T, kind: StmtKind) -> SmallV StmtKind::Empty => smallvec![StmtKind::Empty], StmtKind::MacCall(mut mac) => { let MacCallStmt { mac: mac_, style: _, attrs, tokens: _ } = mac.deref_mut(); - visit_attrs(vis, attrs); + for attr in attrs { + vis.visit_attribute(attr); + } vis.visit_mac_call(mac_); smallvec![StmtKind::MacCall(mac)] } } } - -fn walk_capture_by(vis: &mut T, capture_by: &mut CaptureBy) { - match capture_by { - CaptureBy::Ref => {} - CaptureBy::Value { move_kw } => { - vis.visit_span(move_kw); - } - CaptureBy::Use { use_kw } => { - vis.visit_span(use_kw); - } - } -} - -#[derive(Debug)] -pub enum FnKind<'a> { - /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. - Fn(FnCtxt, &'a mut Visibility, &'a mut Fn), - - /// E.g., `|x, y| body`. - Closure( - &'a mut ClosureBinder, - &'a mut Option, - &'a mut P, - &'a mut P, - ), -} diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 54781e8235e2..9b4535dcfbce 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -1085,6 +1085,7 @@ pub enum NtExprKind { Expr2021 { inferred: bool }, } +/// A macro nonterminal, known in documentation as a fragment specifier. #[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] pub enum NonterminalKind { Item, diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index b8526cf9d952..ad9e5d1468b0 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -3,7 +3,7 @@ use std::{ascii, fmt, str}; use rustc_literal_escaper::{ - MixedUnit, Mode, byte_from_char, unescape_byte, unescape_char, unescape_mixed, unescape_unicode, + MixedUnit, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char, unescape_str, }; use rustc_span::{Span, Symbol, kw, sym}; use tracing::debug; @@ -87,11 +87,10 @@ impl LitKind { // Force-inlining here is aggressive but the closure is // called on every char in the string, so it can be hot in // programs with many long strings containing escapes. - unescape_unicode( + unescape_str( s, - Mode::Str, - &mut #[inline(always)] - |_, c| match c { + #[inline(always)] + |_, res| match res { Ok(c) => buf.push(c), Err(err) => { assert!(!err.is_fatal(), "failed to unescape string literal") @@ -111,8 +110,8 @@ impl LitKind { token::ByteStr => { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); - unescape_unicode(s, Mode::ByteStr, &mut |_, c| match c { - Ok(c) => buf.push(byte_from_char(c)), + unescape_byte_str(s, |_, res| match res { + Ok(b) => buf.push(b), Err(err) => { assert!(!err.is_fatal(), "failed to unescape string literal") } @@ -128,7 +127,7 @@ impl LitKind { token::CStr => { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); - unescape_mixed(s, Mode::CStr, &mut |_span, c| match c { + unescape_c_str(s, |_span, c| match c { Ok(MixedUnit::Char(c)) => { buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()) } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index bd2ab34bfc19..d0c2b2bf68b0 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -65,45 +65,6 @@ impl BoundKind { } } -#[derive(Copy, Clone, Debug)] -pub enum FnKind<'a> { - /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. - Fn(FnCtxt, &'a Visibility, &'a Fn), - - /// E.g., `|x, y| body`. - Closure(&'a ClosureBinder, &'a Option, &'a FnDecl, &'a Expr), -} - -impl<'a> FnKind<'a> { - pub fn header(&self) -> Option<&'a FnHeader> { - match *self { - FnKind::Fn(_, _, Fn { sig, .. }) => Some(&sig.header), - FnKind::Closure(..) => None, - } - } - - pub fn ident(&self) -> Option<&Ident> { - match self { - FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident), - _ => None, - } - } - - pub fn decl(&self) -> &'a FnDecl { - match self { - FnKind::Fn(_, _, Fn { sig, .. }) => &sig.decl, - FnKind::Closure(_, _, decl, _) => decl, - } - } - - pub fn ctxt(&self) -> Option { - match self { - FnKind::Fn(ctxt, ..) => Some(*ctxt), - FnKind::Closure(..) => None, - } - } -} - #[derive(Copy, Clone, Debug)] pub enum LifetimeCtxt { /// Appears in a reference type. @@ -114,206 +75,405 @@ pub enum LifetimeCtxt { GenericArg, } -/// Each method of the `Visitor` trait is a hook to be potentially -/// overridden. Each method's default implementation recursively visits -/// the substructure of the input via the corresponding `walk` method; -/// e.g., the `visit_item` method by default calls `visit::walk_item`. -/// -/// If you want to ensure that your code handles every variant -/// explicitly, you need to override each method. (And you also need -/// to monitor future changes to `Visitor` in case a new method with a -/// new default implementation gets introduced.) -/// -/// Every `walk_*` method uses deconstruction to access fields of structs and -/// enums. This will result in a compile error if a field is added, which makes -/// it more likely the appropriate visit call will be added for it. -pub trait Visitor<'ast>: Sized { - /// The result type of the `visit_*` methods. Can be either `()`, - /// or `ControlFlow`. - type Result: VisitorResult = (); - - fn visit_ident(&mut self, _ident: &'ast Ident) -> Self::Result { - Self::Result::output() - } - fn visit_foreign_mod(&mut self, nm: &'ast ForeignMod) -> Self::Result { - walk_foreign_mod(self, nm) - } - fn visit_foreign_item(&mut self, i: &'ast ForeignItem) -> Self::Result { - walk_item(self, i) - } - fn visit_item(&mut self, i: &'ast Item) -> Self::Result { - walk_item(self, i) - } - fn visit_local(&mut self, l: &'ast Local) -> Self::Result { - walk_local(self, l) - } - fn visit_block(&mut self, b: &'ast Block) -> Self::Result { - walk_block(self, b) - } - fn visit_stmt(&mut self, s: &'ast Stmt) -> Self::Result { - walk_stmt(self, s) - } - fn visit_param(&mut self, param: &'ast Param) -> Self::Result { - walk_param(self, param) - } - fn visit_arm(&mut self, a: &'ast Arm) -> Self::Result { - walk_arm(self, a) - } - fn visit_pat(&mut self, p: &'ast Pat) -> Self::Result { - walk_pat(self, p) - } - fn visit_anon_const(&mut self, c: &'ast AnonConst) -> Self::Result { - walk_anon_const(self, c) - } - fn visit_expr(&mut self, ex: &'ast Expr) -> Self::Result { - walk_expr(self, ex) - } - /// This method is a hack to workaround unstable of `stmt_expr_attributes`. - /// It can be removed once that feature is stabilized. - fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) -> Self::Result { - self.visit_expr(ex) - } - fn visit_ty(&mut self, t: &'ast Ty) -> Self::Result { - walk_ty(self, t) - } - fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result { - walk_ty_pat(self, t) - } - fn visit_generic_param(&mut self, param: &'ast GenericParam) -> Self::Result { - walk_generic_param(self, param) - } - fn visit_generics(&mut self, g: &'ast Generics) -> Self::Result { - walk_generics(self, g) - } - fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) -> Self::Result { - walk_closure_binder(self, b) - } - fn visit_contract(&mut self, c: &'ast FnContract) -> Self::Result { - walk_contract(self, c) - } - fn visit_where_predicate(&mut self, p: &'ast WherePredicate) -> Self::Result { - walk_where_predicate(self, p) - } - fn visit_where_predicate_kind(&mut self, k: &'ast WherePredicateKind) -> Self::Result { - walk_where_predicate_kind(self, k) - } - fn visit_fn(&mut self, fk: FnKind<'ast>, _: Span, _: NodeId) -> Self::Result { - walk_fn(self, fk) - } - fn visit_assoc_item(&mut self, i: &'ast AssocItem, ctxt: AssocCtxt) -> Self::Result { - walk_assoc_item(self, i, ctxt) - } - fn visit_trait_ref(&mut self, t: &'ast TraitRef) -> Self::Result { - walk_trait_ref(self, t) - } - fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) -> Self::Result { - walk_param_bound(self, bounds) - } - fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) -> Self::Result { - walk_precise_capturing_arg(self, arg) - } - fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) -> Self::Result { - walk_poly_trait_ref(self, t) - } - fn visit_variant_data(&mut self, s: &'ast VariantData) -> Self::Result { - walk_variant_data(self, s) - } - fn visit_field_def(&mut self, s: &'ast FieldDef) -> Self::Result { - walk_field_def(self, s) - } - fn visit_variant(&mut self, v: &'ast Variant) -> Self::Result { - walk_variant(self, v) - } - fn visit_variant_discr(&mut self, discr: &'ast AnonConst) -> Self::Result { - self.visit_anon_const(discr) - } - fn visit_label(&mut self, label: &'ast Label) -> Self::Result { - walk_label(self, label) - } - fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) -> Self::Result { - walk_lifetime(self, lifetime) - } - fn visit_mac_call(&mut self, mac: &'ast MacCall) -> Self::Result { - walk_mac(self, mac) - } - fn visit_id(&mut self, _id: NodeId) -> Self::Result { - Self::Result::output() - } - fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) -> Self::Result { - walk_macro_def(self, macro_def) - } - fn visit_path(&mut self, path: &'ast Path) -> Self::Result { - walk_path(self, path) - } - fn visit_use_tree(&mut self, use_tree: &'ast UseTree) -> Self::Result { - walk_use_tree(self, use_tree) - } - fn visit_nested_use_tree(&mut self, use_tree: &'ast UseTree, id: NodeId) -> Self::Result { - try_visit!(self.visit_id(id)); - self.visit_use_tree(use_tree) - } - fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) -> Self::Result { - walk_path_segment(self, path_segment) - } - fn visit_generic_args(&mut self, generic_args: &'ast GenericArgs) -> Self::Result { - walk_generic_args(self, generic_args) - } - fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) -> Self::Result { - walk_generic_arg(self, generic_arg) - } - fn visit_assoc_item_constraint( - &mut self, - constraint: &'ast AssocItemConstraint, - ) -> Self::Result { - walk_assoc_item_constraint(self, constraint) - } - fn visit_attribute(&mut self, attr: &'ast Attribute) -> Self::Result { - walk_attribute(self, attr) - } - fn visit_vis(&mut self, vis: &'ast Visibility) -> Self::Result { - walk_vis(self, vis) - } - fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FnRetTy) -> Self::Result { - walk_fn_ret_ty(self, ret_ty) - } - fn visit_fn_header(&mut self, header: &'ast FnHeader) -> Self::Result { - walk_fn_header(self, header) - } - fn visit_expr_field(&mut self, f: &'ast ExprField) -> Self::Result { - walk_expr_field(self, f) - } - fn visit_pat_field(&mut self, fp: &'ast PatField) -> Self::Result { - walk_pat_field(self, fp) - } - fn visit_crate(&mut self, krate: &'ast Crate) -> Self::Result { - walk_crate(self, krate) - } - fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) -> Self::Result { - walk_inline_asm(self, asm) - } - fn visit_format_args(&mut self, fmt: &'ast FormatArgs) -> Self::Result { - walk_format_args(self, fmt) - } - fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) -> Self::Result { - walk_inline_asm_sym(self, sym) - } - fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) -> Self::Result { - Self::Result::output() - } - fn visit_coroutine_kind(&mut self, coroutine_kind: &'ast CoroutineKind) -> Self::Result { - walk_coroutine_kind(self, coroutine_kind) - } - fn visit_fn_decl(&mut self, fn_decl: &'ast FnDecl) -> Self::Result { - walk_fn_decl(self, fn_decl) - } - fn visit_qself(&mut self, qs: &'ast Option>) -> Self::Result { - walk_qself(self, qs) - } -} - #[macro_export] macro_rules! common_visitor_and_walkers { ($(($mut: ident))? $Visitor:ident$(<$lt:lifetime>)?) => { + $(${ignore($lt)} + #[derive(Copy, Clone)] + )? + #[derive(Debug)] + pub enum FnKind<'a> { + /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. + Fn(FnCtxt, &'a $($mut)? Visibility, &'a $($mut)? Fn), + + /// E.g., `|x, y| body`. + Closure(&'a $($mut)? ClosureBinder, &'a $($mut)? Option, &'a $($mut)? P, &'a $($mut)? P), + } + + impl<'a> FnKind<'a> { + pub fn header(&'a $($mut)? self) -> Option<&'a $($mut)? FnHeader> { + match *self { + FnKind::Fn(_, _, Fn { sig, .. }) => Some(&$($mut)? sig.header), + FnKind::Closure(..) => None, + } + } + + pub fn ident(&'a $($mut)? self) -> Option<&'a $($mut)? Ident> { + match self { + FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident), + _ => None, + } + } + + pub fn decl(&'a $($mut)? self) -> &'a $($mut)? FnDecl { + match self { + FnKind::Fn(_, _, Fn { sig, .. }) => &$($mut)? sig.decl, + FnKind::Closure(_, _, decl, _) => decl, + } + } + + pub fn ctxt(&self) -> Option { + match self { + FnKind::Fn(ctxt, ..) => Some(*ctxt), + FnKind::Closure(..) => None, + } + } + } + + /// Each method of this trait is a hook to be potentially + /// overridden. Each method's default implementation recursively visits + /// the substructure of the input via the corresponding `walk` method; + #[doc = concat!(" e.g., the `visit_item` method by default calls `visit"$(, "_", stringify!($mut))?, "::walk_item`.")] + /// + /// If you want to ensure that your code handles every variant + /// explicitly, you need to override each method. (And you also need + /// to monitor future changes to this trait in case a new method with a + /// new default implementation gets introduced.) + /// + /// Every `walk_*` method uses deconstruction to access fields of structs and + /// enums. This will result in a compile error if a field is added, which makes + /// it more likely the appropriate visit call will be added for it. + pub trait $Visitor<$($lt)?> : Sized $(${ignore($mut)} + MutVisitorResult)? { + $( + ${ignore($lt)} + /// The result type of the `visit_*` methods. Can be either `()`, + /// or `ControlFlow`. + type Result: VisitorResult = (); + )? + + // Methods in this trait have one of three forms, with the last two forms + // only occuring on `MutVisitor`: + // + // fn visit_t(&mut self, t: &mut T); // common + // fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>; // rare + // fn filter_map_t(&mut self, t: T) -> Option; // rarest + // + // When writing these methods, it is better to use destructuring like this: + // + // fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) { + // visit_a(a); + // visit_b(b); + // } + // + // than to use field access like this: + // + // fn visit_abc(&mut self, abc: &mut ABC) { + // visit_a(&mut abc.a); + // visit_b(&mut abc.b); + // // ignore abc.c + // } + // + // As well as being more concise, the former is explicit about which fields + // are skipped. Furthermore, if a new field is added, the destructuring + // version will cause a compile error, which is good. In comparison, the + // field access version will continue working and it would be easy to + // forget to add handling for it. + fn visit_ident(&mut self, Ident { name: _, span }: &$($lt)? $($mut)? Ident) -> Self::Result { + visit_span(self, span) + } + + fn visit_foreign_mod(&mut self, nm: &$($lt)? $($mut)? ForeignMod) -> Self::Result { + walk_foreign_mod(self, nm) + } + + fn visit_foreign_item(&mut self, i: &$($lt)? $($mut)? ForeignItem) -> Self::Result { + walk_item(self, i) + } + + fn visit_item(&mut self, i: &$($lt)? $($mut)? Item) -> Self::Result { + walk_item(self, i) + } + + fn visit_local(&mut self, l: &$($lt)? $($mut)? Local) -> Self::Result { + walk_local(self, l) + } + + fn visit_block(&mut self, b: &$($lt)? $($mut)? Block) -> Self::Result { + walk_block(self, b) + } + + fn visit_param(&mut self, param: &$($lt)? $($mut)? Param) -> Self::Result { + walk_param(self, param) + } + + fn visit_arm(&mut self, a: &$($lt)? $($mut)? Arm) -> Self::Result { + walk_arm(self, a) + } + + fn visit_pat(&mut self, p: &$($lt)? $($mut)? Pat) -> Self::Result { + walk_pat(self, p) + } + + fn visit_anon_const(&mut self, c: &$($lt)? $($mut)? AnonConst) -> Self::Result { + walk_anon_const(self, c) + } + + fn visit_expr(&mut self, ex: &$($lt)? $($mut)? Expr) -> Self::Result { + walk_expr(self, ex) + } + + /// This method is a hack to workaround unstable of `stmt_expr_attributes`. + /// It can be removed once that feature is stabilized. + fn visit_method_receiver_expr(&mut self, ex: &$($lt)? $($mut)? Expr) -> Self::Result { + self.visit_expr(ex) + } + + fn visit_ty(&mut self, t: &$($lt)? $($mut)? Ty) -> Self::Result { + walk_ty(self, t) + } + + fn visit_ty_pat(&mut self, t: &$($lt)? $($mut)? TyPat) -> Self::Result { + walk_ty_pat(self, t) + } + + fn visit_generic_param(&mut self, param: &$($lt)? $($mut)? GenericParam) -> Self::Result { + walk_generic_param(self, param) + } + + fn visit_generics(&mut self, g: &$($lt)? $($mut)? Generics) -> Self::Result { + walk_generics(self, g) + } + fn visit_closure_binder(&mut self, b: &$($lt)? $($mut)? ClosureBinder) -> Self::Result { + walk_closure_binder(self, b) + } + fn visit_contract(&mut self, c: &$($lt)? $($mut)? FnContract) -> Self::Result { + walk_contract(self, c) + } + + fn visit_where_predicate(&mut self, p: &$($lt)? $($mut)? WherePredicate) -> Self::Result { + walk_where_predicate(self, p) + } + + fn visit_where_predicate_kind(&mut self, k: &$($lt)? $($mut)? WherePredicateKind) -> Self::Result { + walk_where_predicate_kind(self, k) + } + + // for `MutVisitor`: `Span` and `NodeId` are mutated at the caller site. + fn visit_fn( + &mut self, + fk: FnKind<$($lt)? $(${ignore($mut)} '_)?>, + _: Span, + _: NodeId + ) -> Self::Result { + walk_fn(self, fk) + } + + fn visit_assoc_item(&mut self, i: &$($lt)? $($mut)? AssocItem, ctxt: AssocCtxt) -> Self::Result { + walk_assoc_item(self, i, ctxt) + } + + fn visit_trait_ref(&mut self, t: &$($lt)? $($mut)? TraitRef) -> Self::Result { + walk_trait_ref(self, t) + } + + fn visit_param_bound(&mut self, bounds: &$($lt)? $($mut)? GenericBound, _ctxt: BoundKind) -> Self::Result { + walk_param_bound(self, bounds) + } + + fn visit_precise_capturing_arg(&mut self, arg: &$($lt)? $($mut)? PreciseCapturingArg) -> Self::Result { + walk_precise_capturing_arg(self, arg) + } + + fn visit_poly_trait_ref(&mut self, t: &$($lt)? $($mut)? PolyTraitRef) -> Self::Result { + walk_poly_trait_ref(self, t) + } + + fn visit_variant_data(&mut self, s: &$($lt)? $($mut)? VariantData) -> Self::Result { + walk_variant_data(self, s) + } + + fn visit_field_def(&mut self, s: &$($lt)? $($mut)? FieldDef) -> Self::Result { + walk_field_def(self, s) + } + + fn visit_variant(&mut self, v: &$($lt)? $($mut)? Variant) -> Self::Result { + walk_variant(self, v) + } + + fn visit_label(&mut self, label: &$($lt)? $($mut)? Label) -> Self::Result { + walk_label(self, label) + } + + fn visit_lifetime(&mut self, lifetime: &$($lt)? $($mut)? Lifetime, $(${ignore($lt)} _: LifetimeCtxt )?) -> Self::Result { + walk_lifetime(self, lifetime) + } + + fn visit_mac_call(&mut self, mac: &$($lt)? $($mut)? MacCall) -> Self::Result { + walk_mac(self, mac) + } + + fn visit_id(&mut self, _id: $(&$mut)? NodeId) -> Self::Result { + Self::Result::output() + } + + fn visit_macro_def(&mut self, macro_def: &$($lt)? $($mut)? MacroDef) -> Self::Result { + walk_macro_def(self, macro_def) + } + + fn visit_path(&mut self, path: &$($lt)? $($mut)? Path) -> Self::Result { + walk_path(self, path) + } + + fn visit_use_tree(&mut self, use_tree: &$($lt)? $($mut)? UseTree) -> Self::Result { + walk_use_tree(self, use_tree) + } + + fn visit_path_segment(&mut self, path_segment: &$($lt)? $($mut)? PathSegment) -> Self::Result { + walk_path_segment(self, path_segment) + } + + fn visit_generic_args(&mut self, generic_args: &$($lt)? $($mut)? GenericArgs) -> Self::Result { + walk_generic_args(self, generic_args) + } + + fn visit_generic_arg(&mut self, generic_arg: &$($lt)? $($mut)? GenericArg) -> Self::Result { + walk_generic_arg(self, generic_arg) + } + + fn visit_assoc_item_constraint( + &mut self, + constraint: &$($lt)? $($mut)? AssocItemConstraint, + ) -> Self::Result { + walk_assoc_item_constraint(self, constraint) + } + + fn visit_attribute(&mut self, attr: &$($lt)? $($mut)? Attribute) -> Self::Result { + walk_attribute(self, attr) + } + + fn visit_vis(&mut self, vis: &$($lt)? $($mut)? Visibility) -> Self::Result { + walk_vis(self, vis) + } + + fn visit_fn_ret_ty(&mut self, ret_ty: &$($lt)? $($mut)? FnRetTy) -> Self::Result { + walk_fn_ret_ty(self, ret_ty) + } + + fn visit_fn_header(&mut self, header: &$($lt)? $($mut)? FnHeader) -> Self::Result { + walk_fn_header(self, header) + } + + fn visit_expr_field(&mut self, f: &$($lt)? $($mut)? ExprField) -> Self::Result { + walk_expr_field(self, f) + } + + fn visit_pat_field(&mut self, fp: &$($lt)? $($mut)? PatField) -> Self::Result { + walk_pat_field(self, fp) + } + + fn visit_crate(&mut self, krate: &$($lt)? $($mut)? Crate) -> Self::Result { + walk_crate(self, krate) + } + + fn visit_inline_asm(&mut self, asm: &$($lt)? $($mut)? InlineAsm) -> Self::Result { + walk_inline_asm(self, asm) + } + + fn visit_format_args(&mut self, fmt: &$($lt)? $($mut)? FormatArgs) -> Self::Result { + walk_format_args(self, fmt) + } + + fn visit_inline_asm_sym(&mut self, sym: &$($lt)? $($mut)? InlineAsmSym) -> Self::Result { + walk_inline_asm_sym(self, sym) + } + + fn visit_capture_by(&mut self, capture_by: &$($lt)? $($mut)? CaptureBy) -> Self::Result { + walk_capture_by(self, capture_by) + } + + fn visit_coroutine_kind(&mut self, coroutine_kind: &$($lt)? $($mut)? CoroutineKind) -> Self::Result { + walk_coroutine_kind(self, coroutine_kind) + } + + fn visit_fn_decl(&mut self, fn_decl: &$($lt)? $($mut)? FnDecl) -> Self::Result { + walk_fn_decl(self, fn_decl) + } + + fn visit_qself(&mut self, qs: &$($lt)? $($mut)? Option>) -> Self::Result { + walk_qself(self, qs) + } + + // (non-mut) `Visitor`-only methods + $( + fn visit_stmt(&mut self, s: &$lt Stmt) -> Self::Result { + walk_stmt(self, s) + } + + fn visit_nested_use_tree(&mut self, use_tree: &$lt UseTree, id: NodeId) -> Self::Result { + try_visit!(self.visit_id(id)); + self.visit_use_tree(use_tree) + } + )? + + // `MutVisitor`-only methods + $( + fn flat_map_foreign_item(&mut self, ni: P) -> SmallVec<[P; 1]> { + walk_flat_map_foreign_item(self, ni) + } + + fn flat_map_item(&mut self, i: P) -> SmallVec<[P; 1]> { + walk_flat_map_item(self, i) + } + + fn flat_map_field_def(&mut self, fd: FieldDef) -> SmallVec<[FieldDef; 1]> { + walk_flat_map_field_def(self, fd) + } + + fn flat_map_assoc_item( + &mut self, + i: P, + ctxt: AssocCtxt, + ) -> SmallVec<[P; 1]> { + walk_flat_map_assoc_item(self, i, ctxt) + } + + fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> { + walk_flat_map_stmt(self, s) + } + + fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> { + walk_flat_map_arm(self, arm) + } + + fn filter_map_expr(&mut self, e: P) -> Option> { + walk_filter_map_expr(self, e) + } + + fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> { + walk_flat_map_variant(self, v) + } + + fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> { + walk_flat_map_param(self, param) + } + + fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> { + walk_flat_map_generic_param(self, param) + } + + fn flat_map_expr_field(&mut self, f: ExprField) -> SmallVec<[ExprField; 1]> { + walk_flat_map_expr_field(self, f) + } + + fn flat_map_where_predicate( + &mut self, + where_predicate: WherePredicate, + ) -> SmallVec<[WherePredicate; 1]> { + walk_flat_map_where_predicate(self, where_predicate) + } + + // Span visiting is no longer used, but we keep it for now, + // in case it's needed for something like #127241. + fn visit_span(&mut self, _sp: &$mut Span) { + // Do nothing. + } + + fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> { + walk_flat_map_pat_field(self, fp) + } + )? + } + pub trait WalkItemKind { type Ctxt; fn walk<$($lt,)? V: $Visitor$(<$lt>)?>( @@ -409,6 +569,24 @@ macro_rules! common_visitor_and_walkers { V::Result::output() } + $(${ignore($lt)} + #[inline] + )? + fn walk_capture_by<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + capture_by: &$($lt)? $($mut)? CaptureBy + ) -> V::Result { + match capture_by { + CaptureBy::Ref => { V::Result::output() } + CaptureBy::Value { move_kw } => { + visit_span(vis, move_kw) + } + CaptureBy::Use { use_kw } => { + visit_span(vis, use_kw) + } + } + } + fn visit_bounds<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, bounds: &$($lt)? $($mut)? GenericBounds, ctxt: BoundKind) -> V::Result { walk_list!(visitor, visit_param_bound, bounds, ctxt); V::Result::output() @@ -989,8 +1167,7 @@ macro_rules! common_visitor_and_walkers { try_visit!(vis.visit_vis(visibility)); try_visit!(vis.visit_ident(ident)); try_visit!(vis.visit_variant_data(data)); - $(${ignore($lt)} visit_opt!(vis, visit_variant_discr, disr_expr); )? - $(${ignore($mut)} visit_opt!(vis, visit_anon_const, disr_expr); )? + visit_opt!(vis, visit_anon_const, disr_expr); visit_span(vis, span) } @@ -1389,7 +1566,7 @@ macro_rules! common_visitor_and_walkers { // FIXME: visit the template exhaustively. pub fn walk_format_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, fmt: &$($lt)? $($mut)? FormatArgs) -> V::Result { - let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _ } = fmt; + let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _, is_source_literal: _ } = fmt; let args = $(${ignore($mut)} arguments.all_args_mut())? $(${ignore($lt)} arguments.all_args())? ; for FormatArgument { kind, expr } in args { match kind { diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 6ac258155fe9..dc571f5c3671 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -11,6 +11,7 @@ doctest = false rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } +rustc_attr_data_structures = { path = "../rustc_attr_data_structures" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 718edad0cc61..c2140514e311 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use rustc_ast::ptr::P as AstP; use rustc_ast::*; use rustc_ast_pretty::pprust::expr_to_string; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::HirId; @@ -831,7 +832,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) { if self.tcx.features().async_fn_track_caller() && let Some(attrs) = self.attrs.get(&outer_hir_id.local_id) - && attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)) + && find_attr!(*attrs, AttributeKind::TrackCaller(_)) { let unstable_span = self.mark_span_with_reason( DesugaringKind::Async, @@ -2289,12 +2290,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> { diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 17b443b8ecc2..943cde90dd20 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -1,12 +1,10 @@ -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; use rustc_session::config::FmtDebug; -use rustc_span::{Ident, Span, Symbol, sym}; +use rustc_span::{DesugaringKind, Ident, Span, Symbol, sym}; use super::LoweringContext; @@ -16,6 +14,13 @@ impl<'hir> LoweringContext<'_, 'hir> { // format_args!() had any arguments _before_ flattening/inlining. let allow_const = fmt.arguments.all_args().is_empty(); let mut fmt = Cow::Borrowed(fmt); + + let sp = self.mark_span_with_reason( + DesugaringKind::FormatLiteral { source: fmt.is_source_literal }, + sp, + sp.ctxt().outer_expn_data().allow_internal_unstable, + ); + if self.tcx.sess.opts.unstable_opts.flatten_format_args { fmt = flatten_format_args(fmt); fmt = self.inline_literals(fmt); @@ -476,77 +481,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: - // &::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: - // &[ - // ::new_display(&arg0), - // ::new_lower_hex(&arg1), - // ::new_debug(&arg2), - // … - // ] - let elements = ctx.arena.alloc_from_iter(arguments.iter().zip(argmap).map( - |(arg, ((_, ty), placeholder_span))| { + // super let args = [::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 => [ - // ::new_display(args.0), - // ::new_lower_hex(args.1), - // ::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 = [ + // ::new_display(args.0), + // ::new_lower_hex(args.1), + // ::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 +547,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: - // ::new_v1_formatted( - // lit_pieces, - // args, - // format_options, - // unsafe { ::core::fmt::UnsafeArg::new() } - // ) + // unsafe { + // ::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: // ::new_v1( @@ -632,37 +601,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 … + // ::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 }; diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index ef27d0ef69b1..8acb51057730 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -2,7 +2,7 @@ use rustc_abi::ExternAbi; use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; -use rustc_errors::ErrorGuaranteed; +use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err}; use rustc_hir::def::{DefKind, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin}; @@ -1644,9 +1644,29 @@ impl<'hir> LoweringContext<'_, 'hir> { self.error_on_invalid_abi(abi_str); ExternAbi::Rust }); - let sess = self.tcx.sess; - let features = self.tcx.features(); - gate_unstable_abi(sess, features, span, extern_abi); + let tcx = self.tcx; + + // we can't do codegen for unsupported ABIs, so error now so we won't get farther + if !tcx.sess.target.is_abi_supported(extern_abi) { + let mut err = struct_span_code_err!( + tcx.dcx(), + span, + E0570, + "{extern_abi} is not a supported ABI for the current target", + ); + + if let ExternAbi::Stdcall { unwind } = extern_abi { + let c_abi = ExternAbi::C { unwind }; + let system_abi = ExternAbi::System { unwind }; + err.help(format!("if you need `extern {extern_abi}` on win32 and `extern {c_abi}` everywhere else, \ + use `extern {system_abi}`" + )); + } + err.emit(); + } + // Show required feature gate even if we already errored, as the user is likely to build the code + // for the actually intended target next and then they will need the feature gate. + gate_unstable_abi(tcx.sess, tcx.features(), span, extern_abi); extern_abi } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e74fd1db15b9..26d7c0cd6d38 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -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)) } diff --git a/compiler/rustc_ast_lowering/src/stability.rs b/compiler/rustc_ast_lowering/src/stability.rs index b8fa2dd3dd62..6752218fa0d4 100644 --- a/compiler/rustc_ast_lowering/src/stability.rs +++ b/compiler/rustc_ast_lowering/src/stability.rs @@ -96,6 +96,9 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> { ExternAbi::RustCold => { Err(UnstableAbi { abi, feature: sym::rust_cold_cc, explain: GateReason::Experimental }) } + ExternAbi::RustInvalid => { + Err(UnstableAbi { abi, feature: sym::rustc_attrs, explain: GateReason::ImplDetail }) + } ExternAbi::GpuKernel => Err(UnstableAbi { abi, feature: sym::abi_gpu_kernel, @@ -124,12 +127,12 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> { feature: sym::abi_riscv_interrupt, explain: GateReason::Experimental, }), - ExternAbi::CCmseNonSecureCall => Err(UnstableAbi { + ExternAbi::CmseNonSecureCall => Err(UnstableAbi { abi, - feature: sym::abi_c_cmse_nonsecure_call, + feature: sym::abi_cmse_nonsecure_call, explain: GateReason::Experimental, }), - ExternAbi::CCmseNonSecureEntry => Err(UnstableAbi { + ExternAbi::CmseNonSecureEntry => Err(UnstableAbi { abi, feature: sym::cmse_nonsecure_entry, explain: GateReason::Experimental, diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index c738cb2aa2fd..1940628b44a5 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -18,5 +18,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } +rustc_target = { path = "../rustc_target" } thin-vec = "0.2.12" # tidy-alphabetical-end diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 9a267501230f..6eddce7b590a 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -1,20 +1,25 @@ -ast_passes_abi_custom_coroutine = - functions with the `"custom"` ABI cannot be `{$coroutine_kind_str}` +ast_passes_abi_cannot_be_coroutine = + functions with the {$abi} ABI cannot be `{$coroutine_kind_str}` .suggestion = remove the `{$coroutine_kind_str}` keyword from this definiton -ast_passes_abi_custom_invalid_signature = - invalid signature for `extern "custom"` function - .note = functions with the `"custom"` ABI cannot have any parameters or return type - .suggestion = remove the parameters and return type - ast_passes_abi_custom_safe_foreign_function = - foreign functions with the `"custom"` ABI cannot be safe + foreign functions with the "custom" ABI cannot be safe .suggestion = remove the `safe` keyword from this definition ast_passes_abi_custom_safe_function = - functions with the `"custom"` ABI must be unsafe + functions with the "custom" ABI must be unsafe .suggestion = add the `unsafe` keyword to this definition +ast_passes_abi_must_not_have_parameters_or_return_type= + invalid signature for `extern {$abi}` function + .note = functions with the {$abi} ABI cannot have any parameters or return type + .suggestion = remove the parameters and return type + +ast_passes_abi_must_not_have_return_type= + invalid signature for `extern {$abi}` function + .note = functions with the "custom" ABI cannot have a return type + .help = remove the return type + ast_passes_assoc_const_without_body = associated constant in `impl` without body .suggestion = provide a definition for the constant diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b69a91e2f5f8..da2482512037 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -21,7 +21,7 @@ use std::ops::{Deref, DerefMut}; use std::str::FromStr; use itertools::{Either, Itertools}; -use rustc_abi::ExternAbi; +use rustc_abi::{CanonAbi, ExternAbi, InterruptKind}; use rustc_ast::ptr::P; use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, walk_list}; use rustc_ast::*; @@ -37,6 +37,7 @@ use rustc_session::lint::builtin::{ }; use rustc_session::lint::{BuiltinLintDiag, LintBuffer}; use rustc_span::{Ident, Span, kw, sym}; +use rustc_target::spec::{AbiMap, AbiMapping}; use thin_vec::thin_vec; use crate::errors::{self, TildeConstReason}; @@ -365,31 +366,77 @@ impl<'a> AstValidator<'a> { } } - /// An `extern "custom"` function must be unsafe, and must not have any parameters or return - /// type. - fn check_custom_abi(&self, ctxt: FnCtxt, ident: &Ident, sig: &FnSig) { + /// Check that the signature of this function does not violate the constraints of its ABI. + fn check_extern_fn_signature(&self, abi: ExternAbi, ctxt: FnCtxt, ident: &Ident, sig: &FnSig) { + match AbiMap::from_target(&self.sess.target).canonize_abi(abi, false) { + AbiMapping::Direct(canon_abi) | AbiMapping::Deprecated(canon_abi) => { + match canon_abi { + CanonAbi::C + | CanonAbi::Rust + | CanonAbi::RustCold + | CanonAbi::Arm(_) + | CanonAbi::GpuKernel + | CanonAbi::X86(_) => { /* nothing to check */ } + + CanonAbi::Custom => { + // An `extern "custom"` function must be unsafe. + self.reject_safe_fn(abi, ctxt, sig); + + // An `extern "custom"` function cannot be `async` and/or `gen`. + self.reject_coroutine(abi, sig); + + // An `extern "custom"` function must have type `fn()`. + self.reject_params_or_return(abi, ident, sig); + } + + CanonAbi::Interrupt(interrupt_kind) => { + // An interrupt handler cannot be `async` and/or `gen`. + self.reject_coroutine(abi, sig); + + if let InterruptKind::X86 = interrupt_kind { + // "x86-interrupt" is special because it does have arguments. + // FIXME(workingjubilee): properly lint on acceptable input types. + if let FnRetTy::Ty(ref ret_ty) = sig.decl.output { + self.dcx().emit_err(errors::AbiMustNotHaveReturnType { + span: ret_ty.span, + abi, + }); + } + } else { + // An `extern "interrupt"` function must have type `fn()`. + self.reject_params_or_return(abi, ident, sig); + } + } + } + } + AbiMapping::Invalid => { /* ignore */ } + } + } + + fn reject_safe_fn(&self, abi: ExternAbi, ctxt: FnCtxt, sig: &FnSig) { let dcx = self.dcx(); - // An `extern "custom"` function must be unsafe. match sig.header.safety { Safety::Unsafe(_) => { /* all good */ } Safety::Safe(safe_span) => { - let safe_span = - self.sess.psess.source_map().span_until_non_whitespace(safe_span.to(sig.span)); + let source_map = self.sess.psess.source_map(); + let safe_span = source_map.span_until_non_whitespace(safe_span.to(sig.span)); dcx.emit_err(errors::AbiCustomSafeForeignFunction { span: sig.span, safe_span }); } Safety::Default => match ctxt { FnCtxt::Foreign => { /* all good */ } FnCtxt::Free | FnCtxt::Assoc(_) => { - self.dcx().emit_err(errors::AbiCustomSafeFunction { + dcx.emit_err(errors::AbiCustomSafeFunction { span: sig.span, + abi, unsafe_span: sig.span.shrink_to_lo(), }); } }, } + } - // An `extern "custom"` function cannot be `async` and/or `gen`. + fn reject_coroutine(&self, abi: ExternAbi, sig: &FnSig) { if let Some(coroutine_kind) = sig.header.coroutine_kind { let coroutine_kind_span = self .sess @@ -397,14 +444,16 @@ impl<'a> AstValidator<'a> { .source_map() .span_until_non_whitespace(coroutine_kind.span().to(sig.span)); - self.dcx().emit_err(errors::AbiCustomCoroutine { + self.dcx().emit_err(errors::AbiCannotBeCoroutine { span: sig.span, + abi, coroutine_kind_span, coroutine_kind_str: coroutine_kind.as_str(), }); } + } - // An `extern "custom"` function must not have any parameters or return type. + fn reject_params_or_return(&self, abi: ExternAbi, ident: &Ident, sig: &FnSig) { let mut spans: Vec<_> = sig.decl.inputs.iter().map(|p| p.span).collect(); if let FnRetTy::Ty(ref ret_ty) = sig.decl.output { spans.push(ret_ty.span); @@ -415,11 +464,12 @@ impl<'a> AstValidator<'a> { let suggestion_span = header_span.shrink_to_hi().to(sig.decl.output.span()); let padding = if header_span.is_empty() { "" } else { " " }; - self.dcx().emit_err(errors::AbiCustomInvalidSignature { + self.dcx().emit_err(errors::AbiMustNotHaveParametersOrReturnType { spans, symbol: ident.name, suggestion_span, padding, + abi, }); } } @@ -1199,9 +1249,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_foreign_fn_bodyless(*ident, body.as_deref()); self.check_foreign_fn_headerless(sig.header); self.check_foreign_item_ascii_only(*ident); - if self.extern_mod_abi == Some(ExternAbi::Custom) { - self.check_custom_abi(FnCtxt::Foreign, ident, sig); - } + self.check_extern_fn_signature( + self.extern_mod_abi.unwrap_or(ExternAbi::FALLBACK), + FnCtxt::Foreign, + ident, + sig, + ); } ForeignItemKind::TyAlias(box TyAlias { defaultness, @@ -1411,9 +1464,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let FnKind::Fn(ctxt, _, fun) = fk && let Extern::Explicit(str_lit, _) = fun.sig.header.ext - && let Ok(ExternAbi::Custom) = ExternAbi::from_str(str_lit.symbol.as_str()) + && let Ok(abi) = ExternAbi::from_str(str_lit.symbol.as_str()) { - self.check_custom_abi(ctxt, &fun.ident, &fun.sig); + self.check_extern_fn_signature(abi, ctxt, &fun.ident, &fun.sig); } self.check_c_variadic_type(fk); diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index c437e62f4d37..d387a4a310ea 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -1,5 +1,6 @@ //! Errors emitted by ast_passes. +use rustc_abi::ExternAbi; use rustc_ast::ParamKindOrd; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic}; @@ -845,6 +846,7 @@ pub(crate) struct AbiCustomSafeForeignFunction { pub(crate) struct AbiCustomSafeFunction { #[primary_span] pub span: Span, + pub abi: ExternAbi, #[suggestion( ast_passes_suggestion, @@ -856,10 +858,11 @@ pub(crate) struct AbiCustomSafeFunction { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_custom_coroutine)] -pub(crate) struct AbiCustomCoroutine { +#[diag(ast_passes_abi_cannot_be_coroutine)] +pub(crate) struct AbiCannotBeCoroutine { #[primary_span] pub span: Span, + pub abi: ExternAbi, #[suggestion( ast_passes_suggestion, @@ -872,11 +875,12 @@ pub(crate) struct AbiCustomCoroutine { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_custom_invalid_signature)] +#[diag(ast_passes_abi_must_not_have_parameters_or_return_type)] #[note] -pub(crate) struct AbiCustomInvalidSignature { +pub(crate) struct AbiMustNotHaveParametersOrReturnType { #[primary_span] pub spans: Vec, + pub abi: ExternAbi, #[suggestion( ast_passes_suggestion, @@ -888,3 +892,13 @@ pub(crate) struct AbiCustomInvalidSignature { pub symbol: Symbol, pub padding: &'static str, } + +#[derive(Diagnostic)] +#[diag(ast_passes_abi_must_not_have_return_type)] +#[note] +pub(crate) struct AbiMustNotHaveReturnType { + #[primary_span] + #[help] + pub span: Span, + pub abi: ExternAbi, +} diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index ee49246a4bbf..7651e8365a29 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -357,6 +357,10 @@ impl<'a> State<'a> { self.word_nbsp("raw"); self.print_mutability(mutability, true); } + ast::BorrowKind::Pin => { + self.word_nbsp("pin"); + self.print_mutability(mutability, true); + } } self.print_expr_cond_paren( expr, @@ -386,18 +390,44 @@ impl<'a> State<'a> { let ib = self.ibox(INDENT_UNIT); - // The Match subexpression in `match x {} - 1` must be parenthesized if - // it is the leftmost subexpression in a statement: - // - // (match x {}) - 1; - // - // But not otherwise: - // - // let _ = match x {} - 1; - // - // Same applies to a small set of other expression kinds which eagerly - // terminate a statement which opens with them. - let needs_par = fixup.would_cause_statement_boundary(expr); + let needs_par = { + // The Match subexpression in `match x {} - 1` must be parenthesized + // if it is the leftmost subexpression in a statement: + // + // (match x {}) - 1; + // + // But not otherwise: + // + // let _ = match x {} - 1; + // + // Same applies to a small set of other expression kinds which + // eagerly terminate a statement which opens with them. + fixup.would_cause_statement_boundary(expr) + } || { + // If a binary operation ends up with an attribute, such as + // resulting from the following macro expansion, then parentheses + // are required so that the attribute encompasses the right + // subexpression and not just the left one. + // + // #![feature(stmt_expr_attributes)] + // + // macro_rules! add_attr { + // ($e:expr) => { #[attr] $e }; + // } + // + // let _ = add_attr!(1 + 1); + // + // We must pretty-print `#[attr] (1 + 1)` not `#[attr] 1 + 1`. + !attrs.is_empty() + && matches!( + expr.kind, + ast::ExprKind::Binary(..) + | ast::ExprKind::Cast(..) + | ast::ExprKind::Assign(..) + | ast::ExprKind::AssignOp(..) + | ast::ExprKind::Range(..) + ) + }; if needs_par { self.popen(); fixup = FixupContext::default(); diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index d4c434560496..dc3598bcc361 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -38,7 +38,8 @@ pub enum InstructionSetAttr { ArmT32, } -#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, HashStable_Generic, Default)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default, PrintAttribute)] +#[derive(Encodable, Decodable, HashStable_Generic)] pub enum OptimizeAttr { /// No `#[optimize(..)]` attribute #[default] @@ -182,6 +183,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), @@ -198,6 +202,9 @@ pub enum AttributeKind { span: Span, }, + /// Represents `#[cold]`. + Cold(Span), + /// Represents `#[rustc_confusables]`. Confusables { symbols: ThinVec, @@ -205,6 +212,9 @@ pub enum AttributeKind { first_span: Span, }, + /// Represents `#[const_continue]`. + ConstContinue(Span), + /// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`. ConstStability { stability: PartialConstStability, @@ -224,17 +234,48 @@ pub enum AttributeKind { /// Represents `#[inline]` and `#[rustc_force_inline]`. Inline(InlineAttr, Span), + /// Represents `#[loop_match]`. + LoopMatch(Span), + /// Represents `#[rustc_macro_transparency]`. MacroTransparency(Transparency), + /// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html). + MayDangle(Span), + + /// Represents `#[must_use]`. + MustUse { + span: Span, + /// must_use can optionally have a reason: `#[must_use = "reason this must be used"]` + reason: Option, + }, + + /// Represents `#[naked]` + Naked(Span), + + /// Represents `#[no_mangle]` + NoMangle(Span), + + /// Represents `#[optimize(size|speed)]` + Optimize(OptimizeAttr, Span), + + /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint). + PubTransparent(Span), + /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations). Repr(ThinVec<(ReprAttr, Span)>), + /// Represents `#[rustc_skip_during_method_dispatch]`. + SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span }, + /// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`. Stability { stability: Stability, /// Span of the attribute. span: Span, }, + + /// Represents `#[track_caller]` + TrackCaller(Span), // tidy-alphabetical-end } diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs new file mode 100644 index 000000000000..e41dd8bde8ff --- /dev/null +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -0,0 +1,42 @@ +use crate::AttributeKind; + +#[derive(PartialEq)] +pub enum EncodeCrossCrate { + Yes, + No, +} + +impl AttributeKind { + pub fn encode_cross_crate(&self) -> EncodeCrossCrate { + use AttributeKind::*; + use EncodeCrossCrate::*; + + match self { + Align { .. } => No, + AllowConstFnUnstable(..) => No, + AllowInternalUnstable(..) => Yes, + AsPtr(..) => Yes, + BodyStability { .. } => No, + Confusables { .. } => Yes, + ConstStability { .. } => Yes, + ConstStabilityIndirect => No, + Deprecation { .. } => Yes, + DocComment { .. } => Yes, + Inline(..) => No, + MacroTransparency(..) => Yes, + Repr(..) => No, + Stability { .. } => Yes, + Cold(..) => No, + ConstContinue(..) => No, + LoopMatch(..) => No, + MayDangle(..) => No, + MustUse { .. } => Yes, + Naked(..) => No, + NoMangle(..) => No, + Optimize(..) => No, + PubTransparent(..) => Yes, + SkipDuringMethodDispatch { .. } => No, + TrackCaller(..) => Yes, + } + } +} diff --git a/compiler/rustc_attr_data_structures/src/lib.rs b/compiler/rustc_attr_data_structures/src/lib.rs index f8355be09adf..86c73f0d9a08 100644 --- a/compiler/rustc_attr_data_structures/src/lib.rs +++ b/compiler/rustc_attr_data_structures/src/lib.rs @@ -9,6 +9,7 @@ // tidy-alphabetical-end mod attributes; +mod encode_cross_crate; mod stability; mod version; @@ -17,6 +18,7 @@ pub mod lints; use std::num::NonZero; pub use attributes::*; +pub use encode_cross_crate::EncodeCrossCrate; use rustc_abi::Align; use rustc_ast::token::CommentKind; use rustc_ast::{AttrStyle, IntTy, UintTy}; diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index b9b386635f63..2bb27ede8605 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -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 @@ -86,6 +89,10 @@ attr_parsing_missing_since = attr_parsing_multiple_stability_levels = multiple stability levels +attr_parsing_naked_functions_incompatible_attribute = + attribute incompatible with `#[unsafe(naked)]` + .label = the `{$attr}` attribute is incompatible with `#[unsafe(naked)]` + .naked_attribute = function marked with `#[unsafe(naked)]` here attr_parsing_non_ident_feature = 'feature' is not an identifier diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs new file mode 100644 index 000000000000..eadf8657a0fd --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -0,0 +1,203 @@ +use rustc_attr_data_structures::{AttributeKind, OptimizeAttr}; +use rustc_feature::{AttributeTemplate, template}; +use rustc_session::parse::feature_err; +use rustc_span::{Span, Symbol, sym}; + +use super::{AcceptMapping, AttributeOrder, AttributeParser, OnDuplicate, SingleAttributeParser}; +use crate::context::{AcceptContext, FinalizeContext, Stage}; +use crate::parser::ArgParser; +use crate::session_diagnostics::NakedFunctionIncompatibleAttribute; + +pub(crate) struct OptimizeParser; + +impl SingleAttributeParser for OptimizeParser { + const PATH: &[Symbol] = &[sym::optimize]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const TEMPLATE: AttributeTemplate = template!(List: "size|speed|none"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + let Some(list) = args.list() else { + cx.expected_list(cx.attr_span); + return None; + }; + + let Some(single) = list.single() else { + cx.expected_single_argument(list.span); + return None; + }; + + let res = match single.meta_item().and_then(|i| i.path().word().map(|i| i.name)) { + Some(sym::size) => OptimizeAttr::Size, + Some(sym::speed) => OptimizeAttr::Speed, + Some(sym::none) => OptimizeAttr::DoNotOptimize, + _ => { + cx.expected_specific_argument(single.span(), vec!["size", "speed", "none"]); + OptimizeAttr::Default + } + }; + + Some(AttributeKind::Optimize(res, cx.attr_span)) + } +} + +pub(crate) struct ColdParser; + +impl SingleAttributeParser for ColdParser { + const PATH: &[Symbol] = &[sym::cold]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(Word); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + return None; + } + + Some(AttributeKind::Cold(cx.attr_span)) + } +} + +#[derive(Default)] +pub(crate) struct NakedParser { + span: Option, +} + +impl AttributeParser for NakedParser { + const ATTRIBUTES: AcceptMapping = + &[(&[sym::naked], template!(Word), |this, cx, args| { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + return; + } + + if let Some(earlier) = this.span { + let span = cx.attr_span; + cx.warn_unused_duplicate(earlier, span); + } else { + this.span = Some(cx.attr_span); + } + })]; + + fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> Option { + // FIXME(jdonszelmann): upgrade this list to *parsed* attributes + // once all of these have parsed forms. That'd make the check much nicer... + // + // many attributes don't make sense in combination with #[naked]. + // Notable attributes that are incompatible with `#[naked]` are: + // + // * `#[inline]` + // * `#[track_caller]` + // * `#[test]`, `#[ignore]`, `#[should_panic]` + // + // NOTE: when making changes to this list, check that `error_codes/E0736.md` remains + // accurate. + const ALLOW_LIST: &[rustc_span::Symbol] = &[ + // conditional compilation + sym::cfg_trace, + sym::cfg_attr_trace, + // testing (allowed here so better errors can be generated in `rustc_builtin_macros::test`) + sym::test, + sym::ignore, + sym::should_panic, + sym::bench, + // diagnostics + sym::allow, + sym::warn, + sym::deny, + sym::forbid, + sym::deprecated, + sym::must_use, + // abi, linking and FFI + sym::cold, + sym::export_name, + sym::link_section, + sym::linkage, + sym::no_mangle, + sym::instruction_set, + sym::repr, + sym::rustc_std_internal_symbol, + sym::align, + // obviously compatible with self + sym::naked, + // documentation + sym::doc, + ]; + + let span = self.span?; + + // only if we found a naked attribute do we do the somewhat expensive check + 'outer: for other_attr in cx.all_attrs { + for allowed_attr in ALLOW_LIST { + if other_attr.segments().next().is_some_and(|i| cx.tools.contains(&i.name)) { + // effectively skips the error message being emitted below + // if it's a tool attribute + continue 'outer; + } + if other_attr.word_is(*allowed_attr) { + // effectively skips the error message being emitted below + // if its an allowed attribute + continue 'outer; + } + + if other_attr.word_is(sym::target_feature) { + if !cx.features().naked_functions_target_feature() { + feature_err( + &cx.sess(), + sym::naked_functions_target_feature, + other_attr.span(), + "`#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions", + ).emit(); + } + + continue 'outer; + } + } + + cx.emit_err(NakedFunctionIncompatibleAttribute { + span: other_attr.span(), + naked_span: span, + attr: other_attr.get_attribute_path().to_string(), + }); + } + + Some(AttributeKind::Naked(span)) + } +} + +pub(crate) struct TrackCallerParser; + +impl SingleAttributeParser for TrackCallerParser { + const PATH: &[Symbol] = &[sym::track_caller]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(Word); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + return None; + } + + Some(AttributeKind::TrackCaller(cx.attr_span)) + } +} + +pub(crate) struct NoMangleParser; + +impl SingleAttributeParser for NoMangleParser { + const PATH: &[rustc_span::Symbol] = &[sym::no_mangle]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(Word); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + return None; + } + + Some(AttributeKind::NoMangle(cx.attr_span)) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index 25efc3ae49b9..11844f4cd950 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -45,10 +45,8 @@ impl SingleAttributeParser for InlineParser { ArgParser::NameValue(_) => { let suggestions = >::TEMPLATE.suggestions(false, "inline"); - cx.emit_lint( - AttributeLintKind::IllFormedAttributeInput { suggestions }, - cx.attr_span, - ); + let span = cx.attr_span; + cx.emit_lint(AttributeLintKind::IllFormedAttributeInput { suggestions }, span); return None; } } diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs index d4c846de56eb..1c8fc5079dad 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs @@ -14,8 +14,25 @@ impl SingleAttributeParser for AsPtrParser { const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const TEMPLATE: AttributeTemplate = template!(Word); - fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option { - // FIXME: check that there's no args (this is currently checked elsewhere) + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + } Some(AttributeKind::AsPtr(cx.attr_span)) } } + +pub(crate) struct PubTransparentParser; +impl SingleAttributeParser for PubTransparentParser { + const PATH: &[Symbol] = &[sym::rustc_pub_transparent]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const TEMPLATE: AttributeTemplate = template!(Word); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + } + Some(AttributeKind::PubTransparent(cx.attr_span)) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs new file mode 100644 index 000000000000..f6c7ac5e3a39 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs @@ -0,0 +1,31 @@ +use rustc_attr_data_structures::AttributeKind; +use rustc_feature::{AttributeTemplate, template}; +use rustc_span::{Symbol, sym}; + +use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; +use crate::context::{AcceptContext, Stage}; +use crate::parser::ArgParser; + +pub(crate) struct LoopMatchParser; +impl SingleAttributeParser for LoopMatchParser { + const PATH: &[Symbol] = &[sym::loop_match]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(Word); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option { + Some(AttributeKind::LoopMatch(cx.attr_span)) + } +} + +pub(crate) struct ConstContinueParser; +impl SingleAttributeParser for ConstContinueParser { + const PATH: &[Symbol] = &[sym::const_continue]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(Word); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option { + Some(AttributeKind::ConstContinue(cx.attr_span)) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index fa2a6087506c..d407669cb410 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -17,7 +17,6 @@ use std::marker::PhantomData; use rustc_attr_data_structures::AttributeKind; -use rustc_attr_data_structures::lints::AttributeLintKind; use rustc_feature::AttributeTemplate; use rustc_span::{Span, Symbol}; use thin_vec::ThinVec; @@ -28,12 +27,17 @@ use crate::session_diagnostics::UnusedMultiple; pub(crate) mod allow_unstable; pub(crate) mod cfg; +pub(crate) mod codegen_attrs; pub(crate) mod confusables; pub(crate) mod deprecation; pub(crate) mod inline; pub(crate) mod lint_helpers; +pub(crate) mod loop_match; +pub(crate) mod must_use; pub(crate) mod repr; +pub(crate) mod semantics; pub(crate) mod stability; +pub(crate) mod traits; pub(crate) mod transparency; pub(crate) mod util; @@ -86,8 +90,19 @@ pub(crate) trait AttributeParser: Default + 'static { /// [`SingleAttributeParser`] can only convert attributes one-to-one, and cannot combine multiple /// attributes together like is necessary for `#[stable()]` and `#[unstable()]` for example. pub(crate) trait SingleAttributeParser: 'static { + /// The single path of the attribute this parser accepts. + /// + /// If you need the parser to accept more than one path, use [`AttributeParser`] instead const PATH: &[Symbol]; + + /// Configures the precedence of attributes with the same `PATH` on a syntax node. const ATTRIBUTE_ORDER: AttributeOrder; + + /// Configures what to do when when the same attribute is + /// applied more than once on the same syntax node. + /// + /// [`ATTRIBUTE_ORDER`](Self::ATTRIBUTE_ORDER) specified which one is assumed to be correct, + /// and this specified whether to, for example, warn or error on the other one. const ON_DUPLICATE: OnDuplicate; /// The template this attribute parser should implement. Used for diagnostics. @@ -97,6 +112,8 @@ pub(crate) trait SingleAttributeParser: 'static { fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option; } +/// Use in combination with [`SingleAttributeParser`]. +/// `Single` implements [`AttributeParser`]. pub(crate) struct Single, S: Stage>( PhantomData<(S, T)>, Option<(AttributeKind, Span)>, @@ -173,14 +190,8 @@ impl OnDuplicate { unused: Span, ) { match self { - OnDuplicate::Warn => cx.emit_lint( - AttributeLintKind::UnusedDuplicate { this: unused, other: used, warning: false }, - unused, - ), - OnDuplicate::WarnButFutureError => cx.emit_lint( - AttributeLintKind::UnusedDuplicate { this: unused, other: used, warning: true }, - unused, - ), + OnDuplicate::Warn => cx.warn_unused_duplicate(used, unused), + OnDuplicate::WarnButFutureError => cx.warn_unused_duplicate_future_error(used, unused), OnDuplicate::Error => { cx.emit_err(UnusedMultiple { this: used, @@ -229,6 +240,10 @@ pub(crate) trait CombineAttributeParser: 'static { const PATH: &[rustc_span::Symbol]; type Item; + /// A function that converts individual items (of type [`Item`](Self::Item)) into the final attribute. + /// + /// For example, individual representations fomr `#[repr(...)]` attributes into an `AttributeKind::Repr(x)`, + /// where `x` is a vec of these individual reprs. const CONVERT: ConvertFn; /// The template this attribute parser should implement. Used for diagnostics. @@ -241,6 +256,8 @@ pub(crate) trait CombineAttributeParser: 'static { ) -> impl IntoIterator + 'c; } +/// Use in combination with [`CombineAttributeParser`]. +/// `Combine` implements [`AttributeParser`]. pub(crate) struct Combine, S: Stage>( PhantomData<(S, T)>, ThinVec<>::Item>, diff --git a/compiler/rustc_attr_parsing/src/attributes/must_use.rs b/compiler/rustc_attr_parsing/src/attributes/must_use.rs new file mode 100644 index 000000000000..a672d9561274 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/must_use.rs @@ -0,0 +1,40 @@ +use rustc_attr_data_structures::AttributeKind; +use rustc_errors::DiagArgValue; +use rustc_feature::{AttributeTemplate, template}; +use rustc_span::{Symbol, sym}; + +use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; +use crate::context::{AcceptContext, Stage}; +use crate::parser::ArgParser; +use crate::session_diagnostics; + +pub(crate) struct MustUseParser; + +impl SingleAttributeParser for MustUseParser { + const PATH: &[Symbol] = &[sym::must_use]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const TEMPLATE: AttributeTemplate = template!(Word, NameValueStr: "reason"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + Some(AttributeKind::MustUse { + span: cx.attr_span, + reason: match args { + ArgParser::NoArgs => None, + ArgParser::NameValue(name_value) => name_value.value_as_str(), + ArgParser::List(_) => { + let suggestions = + >::TEMPLATE.suggestions(false, "must_use"); + cx.emit_err(session_diagnostics::MustUseIllFormedAttributeInput { + num_suggestions: suggestions.len(), + suggestions: DiagArgValue::StrListSepByAnd( + suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), + ), + span: cx.attr_span, + }); + return None; + } + }, + }) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index ae9e7871874d..4aa27043e989 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -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; @@ -25,7 +25,8 @@ impl CombineAttributeParser for ReprParser { const PATH: &[Symbol] = &[sym::repr]; const CONVERT: ConvertFn = AttributeKind::Repr; // FIXME(jdonszelmann): never used - const TEMPLATE: AttributeTemplate = template!(List: "C"); + const TEMPLATE: AttributeTemplate = + template!(List: "C | Rust | align(...) | packed(...) | | transparent"); fn extend<'c>( cx: &'c mut AcceptContext<'_, '_, S>, @@ -203,7 +204,7 @@ fn parse_repr_align( }); } Align => { - cx.dcx().emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg { + cx.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg { span: param_span, }); } @@ -266,3 +267,57 @@ fn parse_alignment(node: &LitKind) -> Result { 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!(List: ""); + + 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 AttributeParser for AlignParser { + const ATTRIBUTES: AcceptMapping = &[(Self::PATH, Self::TEMPLATE, Self::parse)]; + + fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option { + let (align, span) = self.0?; + Some(AttributeKind::Align { align, span }) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/semantics.rs b/compiler/rustc_attr_parsing/src/attributes/semantics.rs new file mode 100644 index 000000000000..54f50445fbdf --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/semantics.rs @@ -0,0 +1,22 @@ +use rustc_attr_data_structures::AttributeKind; +use rustc_feature::{AttributeTemplate, template}; +use rustc_span::{Symbol, sym}; + +use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; +use crate::context::{AcceptContext, Stage}; +use crate::parser::ArgParser; + +pub(crate) struct MayDangleParser; +impl SingleAttributeParser for MayDangleParser { + const PATH: &[Symbol] = &[sym::may_dangle]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(Word); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + } + Some(AttributeKind::MayDangle(cx.attr_span)) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 6871ff4ec9f3..37104855623f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -139,7 +139,10 @@ impl SingleAttributeParser for ConstStabilityIndirectParser { const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore; const TEMPLATE: AttributeTemplate = template!(Word); - fn convert(_cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option { + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + } Some(AttributeKind::ConstStabilityIndirect) } } @@ -361,8 +364,8 @@ pub(crate) fn parse_unstability( }; } Some(sym::soft) => { - if !param.args().no_args() { - cx.emit_err(session_diagnostics::SoftNoArgs { span: param.span() }); + if let Err(span) = args.no_args() { + cx.emit_err(session_diagnostics::SoftNoArgs { span }); } is_soft = true; } diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs new file mode 100644 index 000000000000..83a98c53c7f7 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -0,0 +1,54 @@ +use core::mem; + +use rustc_attr_data_structures::AttributeKind; +use rustc_feature::{AttributeTemplate, template}; +use rustc_span::{Symbol, sym}; + +use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; +use crate::context::{AcceptContext, Stage}; +use crate::parser::ArgParser; + +pub(crate) struct SkipDuringMethodDispatchParser; + +impl SingleAttributeParser for SkipDuringMethodDispatchParser { + const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + + const TEMPLATE: AttributeTemplate = template!(List: "array, boxed_slice"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + let mut array = false; + let mut boxed_slice = false; + let Some(args) = args.list() else { + cx.expected_list(cx.attr_span); + return None; + }; + if args.is_empty() { + cx.expected_at_least_one_argument(args.span); + return None; + } + for arg in args.mixed() { + let Some(arg) = arg.meta_item() else { + cx.unexpected_literal(arg.span()); + continue; + }; + if let Err(span) = arg.args().no_args() { + cx.expected_no_args(span); + } + let path = arg.path(); + let (key, skip): (Symbol, &mut bool) = match path.word_sym() { + Some(key @ sym::array) => (key, &mut array), + Some(key @ sym::boxed_slice) => (key, &mut boxed_slice), + _ => { + cx.expected_specific_argument(path.span(), vec!["array", "boxed_slice"]); + continue; + } + }; + if mem::replace(skip, true) { + cx.duplicate_key(arg.span(), key); + } + } + Some(AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: cx.attr_span }) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 51c1760da300..6ca5c64e0bc5 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -15,17 +15,24 @@ use rustc_session::Session; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser}; +use crate::attributes::codegen_attrs::{ + ColdParser, NakedParser, NoMangleParser, OptimizeParser, TrackCallerParser, +}; 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::lint_helpers::{AsPtrParser, PubTransparentParser}; +use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser}; +use crate::attributes::must_use::MustUseParser; +use crate::attributes::repr::{AlignParser, ReprParser}; +use crate::attributes::semantics::MayDangleParser; use crate::attributes::stability::{ BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser, }; +use crate::attributes::traits::SkipDuringMethodDispatchParser; use crate::attributes::transparency::TransparencyParser; use crate::attributes::{AttributeParser as _, Combine, Single}; -use crate::parser::{ArgParser, MetaItemParser}; +use crate::parser::{ArgParser, MetaItemParser, PathParser}; use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem}; macro_rules! group_type { @@ -90,9 +97,11 @@ macro_rules! attribute_parsers { attribute_parsers!( pub(crate) static ATTRIBUTE_PARSERS = [ // tidy-alphabetical-start + AlignParser, BodyStabilityParser, ConfusablesParser, ConstStabilityParser, + NakedParser, StabilityParser, // tidy-alphabetical-end @@ -104,10 +113,20 @@ attribute_parsers!( // tidy-alphabetical-start Single, + Single, + Single, Single, Single, Single, + Single, + Single, + Single, + Single, + Single, + Single, Single, + Single, + Single, Single, // tidy-alphabetical-end ]; @@ -164,7 +183,7 @@ pub struct Late; /// /// Gives [`AttributeParser`]s enough information to create errors, for example. pub(crate) struct AcceptContext<'f, 'sess, S: Stage> { - pub(crate) finalize_cx: FinalizeContext<'f, 'sess, S>, + pub(crate) shared: SharedContext<'f, 'sess, S>, /// The span of the attribute currently being parsed pub(crate) attr_span: Span, @@ -177,7 +196,7 @@ pub(crate) struct AcceptContext<'f, 'sess, S: Stage> { pub(crate) attr_path: AttrPath, } -impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { +impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> { pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed { S::emit_err(&self.sess, diag) } @@ -190,6 +209,34 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { (self.emit_lint)(AttributeLint { id, span, kind: lint }); } + pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) { + self.emit_lint( + AttributeLintKind::UnusedDuplicate { + this: unused_span, + other: used_span, + warning: false, + }, + unused_span, + ) + } + + pub(crate) fn warn_unused_duplicate_future_error( + &mut self, + used_span: Span, + unused_span: Span, + ) { + self.emit_lint( + AttributeLintKind::UnusedDuplicate { + this: unused_span, + other: used_span, + warning: true, + }, + unused_span, + ) + } +} + +impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { pub(crate) fn unknown_key( &self, span: Span, @@ -231,6 +278,16 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { }) } + pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed { + self.emit_err(AttributeParseError { + span: args_span, + attr_span: self.attr_span, + template: self.template.clone(), + attribute: self.attr_path.clone(), + reason: AttributeParseErrorReason::ExpectedNoArgs, + }) + } + /// emit an error that a `name = value` pair was expected at this span. The symbol can be given for /// a nicer error message talking about the specific name that was found lacking a value. pub(crate) fn expected_name_value(&self, span: Span, name: Option) -> ErrorGuaranteed { @@ -276,6 +333,16 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { }) } + pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed { + self.emit_err(AttributeParseError { + span, + attr_span: self.attr_span, + template: self.template.clone(), + attribute: self.attr_path.clone(), + reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument, + }) + } + pub(crate) fn expected_specific_argument( &self, span: Span, @@ -312,16 +379,16 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { } impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> { - type Target = FinalizeContext<'f, 'sess, S>; + type Target = SharedContext<'f, 'sess, S>; fn deref(&self) -> &Self::Target { - &self.finalize_cx + &self.shared } } impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> { fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.finalize_cx + &mut self.shared } } @@ -329,7 +396,7 @@ impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> { /// /// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create /// errors, for example. -pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> { +pub(crate) struct SharedContext<'p, 'sess, S: Stage> { /// The parse context, gives access to the session and the /// diagnostics context. pub(crate) cx: &'p mut AttributeParser<'sess, S>, @@ -338,10 +405,40 @@ pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> { /// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to pub(crate) target_id: S::Id, - pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint), + emit_lint: &'p mut dyn FnMut(AttributeLint), +} + +/// Context given to every attribute parser during finalization. +/// +/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create +/// errors, for example. +pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> { + pub(crate) shared: SharedContext<'p, 'sess, S>, + + /// A list of all attribute on this syntax node. + /// + /// Useful for compatibility checks with other attributes in [`finalize`](crate::attributes::AttributeParser::finalize) + /// + /// Usually, you should use normal attribute parsing logic instead, + /// especially when making a *denylist* of other attributes. + pub(crate) all_attrs: &'p [PathParser<'p>], } impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> { + type Target = SharedContext<'p, 'sess, S>; + + fn deref(&self) -> &Self::Target { + &self.shared + } +} + +impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.shared + } +} + +impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> { type Target = AttributeParser<'sess, S>; fn deref(&self) -> &Self::Target { @@ -349,7 +446,7 @@ impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> { } } -impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> { +impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> { fn deref_mut(&mut self) -> &mut Self::Target { self.cx } @@ -364,8 +461,7 @@ pub enum OmitDoc { /// Context created once, for example as part of the ast lowering /// context, through which all attributes can be lowered. pub struct AttributeParser<'sess, S: Stage = Late> { - #[expect(dead_code)] // FIXME(jdonszelmann): needed later to verify we parsed all attributes - tools: Vec, + pub(crate) tools: Vec, features: Option<&'sess Features>, sess: &'sess Session, stage: PhantomData, @@ -419,19 +515,13 @@ impl<'sess> AttributeParser<'sess, Early> { parsed.pop() } - - pub fn new_early(sess: &'sess Session, features: &'sess Features, tools: Vec) -> Self { - Self { features: Some(features), tools, parse_only: None, sess, stage: PhantomData } - } -} - -impl<'sess> AttributeParser<'sess, Late> { - pub fn new(sess: &'sess Session, features: &'sess Features, tools: Vec) -> Self { - Self { features: Some(features), tools, parse_only: None, sess, stage: PhantomData } - } } impl<'sess, S: Stage> AttributeParser<'sess, S> { + pub fn new(sess: &'sess Session, features: &'sess Features, tools: Vec) -> Self { + Self { features: Some(features), tools, parse_only: None, sess, stage: PhantomData } + } + pub(crate) fn sess(&self) -> &'sess Session { &self.sess } @@ -459,6 +549,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { mut emit_lint: impl FnMut(AttributeLint), ) -> Vec { let mut attributes = Vec::new(); + let mut attr_paths = Vec::new(); for attr in attrs { // If we're only looking for a single attribute, skip all the ones we don't care about. @@ -502,6 +593,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { // })) // } ast::AttrKind::Normal(n) => { + attr_paths.push(PathParser::Ast(&n.item.path)); + let parser = MetaItemParser::from_attr(n, self.dcx()); let path = parser.path(); let args = parser.args(); @@ -510,7 +603,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { if let Some(accepts) = S::parsers().0.get(parts.as_slice()) { for (template, accept) in accepts { let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext { - finalize_cx: FinalizeContext { + shared: SharedContext { cx: self, target_span, target_id, @@ -554,10 +647,13 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { let mut parsed_attributes = Vec::new(); for f in &S::parsers().1 { if let Some(attr) = f(&mut FinalizeContext { - cx: self, - target_span, - target_id, - emit_lint: &mut emit_lint, + shared: SharedContext { + cx: self, + target_span, + target_id, + emit_lint: &mut emit_lint, + }, + all_attrs: &attr_paths, }) { parsed_attributes.push(Attribute::Parsed(attr)); } diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 1edbe3a9d27a..aecaae947c99 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -87,6 +87,14 @@ impl<'a> PathParser<'a> { pub fn word_is(&self, sym: Symbol) -> bool { self.word().map(|i| i.name == sym).unwrap_or(false) } + + /// Checks whether the first segments match the givens. + /// + /// Unlike [`segments_is`](Self::segments_is), + /// `self` may contain more segments than the number matched against. + pub fn starts_with(&self, segments: &[Symbol]) -> bool { + segments.len() < self.len() && self.segments().zip(segments).all(|(a, b)| a.name == *b) + } } impl Display for PathParser<'_> { @@ -161,9 +169,15 @@ impl<'a> ArgParser<'a> { } } - /// Asserts that there are no arguments - pub fn no_args(&self) -> bool { - matches!(self, Self::NoArgs) + /// Assert that there were no args. + /// If there were, get a span to the arguments + /// (to pass to [`AcceptContext::expected_no_args`](crate::context::AcceptContext::expected_no_args)). + pub fn no_args(&self) -> Result<(), Span> { + match self { + Self::NoArgs => Ok(()), + Self::List(args) => Err(args.span), + Self::NameValue(args) => Err(args.eq_span.to(args.value_span)), + } } } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 57ac92a0ca19..263b323e3eb1 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -436,6 +436,15 @@ pub(crate) struct IllFormedAttributeInput { pub suggestions: DiagArgValue, } +#[derive(Diagnostic)] +#[diag(attr_parsing_ill_formed_attribute_input)] +pub(crate) struct MustUseIllFormedAttributeInput { + #[primary_span] + pub span: Span, + pub num_suggestions: usize, + pub suggestions: DiagArgValue, +} + #[derive(Diagnostic)] #[diag(attr_parsing_stability_outside_std, code = E0734)] pub(crate) struct StabilityOutsideStd { @@ -450,6 +459,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 { @@ -465,8 +482,21 @@ pub(crate) struct UnrecognizedReprHint { pub span: Span, } +#[derive(Diagnostic)] +#[diag(attr_parsing_naked_functions_incompatible_attribute, code = E0736)] +pub(crate) struct NakedFunctionIncompatibleAttribute { + #[primary_span] + #[label] + pub span: Span, + #[label(attr_parsing_naked_attribute)] + pub naked_span: Span, + pub attr: String, +} + pub(crate) enum AttributeParseErrorReason { + ExpectedNoArgs, ExpectedStringLiteral { byte_string: Option }, + ExpectedAtLeastOneArgument, ExpectedSingleArgument, ExpectedList, UnexpectedLiteral, @@ -510,6 +540,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError { diag.span_label(self.span, "expected a single argument here"); diag.code(E0805); } + AttributeParseErrorReason::ExpectedAtLeastOneArgument => { + diag.span_label(self.span, "expected at least 1 argument here"); + } AttributeParseErrorReason::ExpectedList => { diag.span_label(self.span, "expected this to be a list"); } @@ -521,6 +554,10 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError { diag.span_label(self.span, format!("didn't expect a literal here")); diag.code(E0565); } + AttributeParseErrorReason::ExpectedNoArgs => { + diag.span_label(self.span, format!("didn't expect any arguments here")); + diag.code(E0565); + } AttributeParseErrorReason::ExpectedNameValue(None) => { diag.span_label( self.span, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 34d368499397..98dc898db232 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3201,14 +3201,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let expr_ty: Option> = 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 "); - } + 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; } diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 095c0df98acc..f9e52239d6f6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -71,7 +71,6 @@ impl<'tcx> BorrowExplanation<'tcx> { ) { let tcx = cx.infcx.tcx; let body = cx.body; - let local_names = &cx.local_names; if let Some(span) = borrow_span { let def_id = body.source.def_id(); @@ -220,7 +219,7 @@ impl<'tcx> BorrowExplanation<'tcx> { _ => ("destructor", format!("type `{}`", local_decl.ty)), }; - match local_names[dropped_local] { + match cx.local_name(dropped_local) { Some(local_name) if !local_decl.from_compiler_desugaring() => { let message = format!( "{borrow_desc}borrow might be used here, when `{local_name}` is dropped \ @@ -670,10 +669,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { Some(Cause::DropVar(local, location)) => { let mut should_note_order = false; - if self.local_names[local].is_some() + if self.local_name(local).is_some() && let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place && let Some(borrowed_local) = place.as_local() - && self.local_names[borrowed_local].is_some() + && self.local_name(borrowed_local).is_some() && local != borrowed_local { should_note_order = true; @@ -748,7 +747,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { Operand::Copy(place) | Operand::Move(place) => { if let Some(l) = place.as_local() { let local_decl = &self.body.local_decls[l]; - if self.local_names[l].is_none() { + if self.local_name(l).is_none() { local_decl.source_info.span } else { span @@ -793,7 +792,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { Operand::Copy(place) | Operand::Move(place) => { if let Some(l) = place.as_local() { let local_decl = &self.body.local_decls[l]; - if self.local_names[l].is_none() { + if self.local_name(l).is_none() { local_decl.source_info.span } else { span diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 5e3f3ffa2ea8..9ad91d605a77 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -7,17 +7,17 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, listify}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::{self as hir, CoroutineKind, LangItem}; -use rustc_index::IndexSlice; +use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::{BoundRegionConversionTime, NllRegionVariableOrigin}; use rustc_infer::traits::SelectionError; -use rustc_middle::bug; use rustc_middle::mir::{ AggregateKind, CallSource, ConstOperand, ConstraintCategory, FakeReadCause, Local, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef, PlaceTy, ProjectionElem, Rvalue, Statement, - StatementKind, Terminator, TerminatorKind, find_self_call, + StatementKind, Terminator, TerminatorKind, VarDebugInfoContents, find_self_call, }; use rustc_middle::ty::print::Print; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveOutIndex}; use rustc_span::def_id::LocalDefId; use rustc_span::source_map::Spanned; @@ -190,6 +190,36 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ) -> Option<&(PlaceRef<'tcx>, Diag<'infcx>)> { self.diags_buffer.buffered_move_errors.get(move_out_indices) } + + /// Uses `body.var_debug_info` to find the symbol + fn local_name(&self, index: Local) -> Option { + *self.local_names().get(index)? + } + + fn local_names(&self) -> &IndexSlice> { + self.local_names.get_or_init(|| { + let mut local_names = IndexVec::from_elem(None, &self.body.local_decls); + for var_debug_info in &self.body.var_debug_info { + if let VarDebugInfoContents::Place(place) = var_debug_info.value { + if let Some(local) = place.as_local() { + if let Some(prev_name) = local_names[local] + && var_debug_info.name != prev_name + { + span_bug!( + var_debug_info.source_info.span, + "local {:?} has many names (`{}` vs `{}`)", + local, + prev_name, + var_debug_info.name + ); + } + local_names[local] = Some(var_debug_info.name); + } + } + } + local_names + }) + } } impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { @@ -430,7 +460,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// a name, or its name was generated by the compiler, then `Err` is returned fn append_local_to_string(&self, local: Local, buf: &mut String) -> Result<(), ()> { let decl = &self.body.local_decls[local]; - match self.local_names[local] { + match self.local_name(local) { Some(name) if !decl.from_compiler_desugaring() => { buf.push_str(name.as_str()); Ok(()) @@ -1254,8 +1284,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { && !spans.is_empty() { let mut span: MultiSpan = spans.clone().into(); + err.arg("ty", param_ty.to_string()); + let msg = err.dcx.eagerly_translate_to_string( + fluent::borrowck_moved_a_fn_once_in_call_def, + err.args.iter(), + ); + err.remove_arg("ty"); for sp in spans { - span.push_span_label(sp, fluent::borrowck_moved_a_fn_once_in_call_def); + span.push_span_label(sp, msg.clone()); } span.push_span_label( fn_call_span, @@ -1500,4 +1536,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } } + + /// Skip over locals that begin with an underscore or have no name + pub(crate) fn local_excluded_from_unused_mut_lint(&self, index: Local) -> bool { + self.local_name(index).is_none_or(|name| name.as_str().starts_with('_')) + } } diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 0394a42ea9c7..b21d348183fc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -465,11 +465,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let PlaceRef { local, projection: [] } = deref_base { let decl = &self.body.local_decls[local]; + let local_name = self.local_name(local).map(|sym| format!("`{sym}`")); if decl.is_ref_for_guard() { return self .cannot_move_out_of( span, - &format!("`{}` in pattern guard", self.local_names[local].unwrap()), + &format!( + "{} in pattern guard", + local_name.as_deref().unwrap_or("the place") + ), ) .with_note( "variables bound in patterns cannot be moved from \ @@ -825,7 +829,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } if binds_to.len() == 1 { - let place_desc = &format!("`{}`", self.local_names[*local].unwrap()); + let place_desc = self.local_name(*local).map(|sym| format!("`{sym}`")); if let Some(expr) = self.find_expr(binding_span) { self.suggest_cloning(err, bind_to.ty, expr, None); @@ -834,7 +838,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, ty: bind_to.ty, - place: place_desc, + place: place_desc.as_deref().unwrap_or("the place"), span: binding_span, }); } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index a5c9bad3ac2d..fd8a2a6bc354 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -60,7 +60,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if access_place.as_local().is_some() { reason = ", as it is not declared as mutable".to_string(); } else { - let name = self.local_names[local].expect("immutable unnamed local"); + let name = self.local_name(local).expect("immutable unnamed local"); reason = format!(", as `{name}` is not declared as mutable"); } } @@ -285,7 +285,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .body .local_decls .get(local) - .is_some_and(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) => + .is_some_and(|l| mut_borrow_of_mutable_ref(l, self.local_name(local))) => { let decl = &self.body.local_decls[local]; err.span_label(span, format!("cannot {act}")); @@ -481,7 +481,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let (pointer_sigil, pointer_desc) = if local_decl.ty.is_ref() { ("&", "reference") } else { ("*const", "pointer") }; - match self.local_names[local] { + match self.local_name(local) { Some(name) if !local_decl.from_compiler_desugaring() => { err.span_label( span, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 3bec07afa0fe..d27e08573e03 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -664,14 +664,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region( self.infcx.tcx, self.body, - &self.local_names, + &self.local_names(), &self.upvars, errci.fr, ); let outlived_fr_name_and_span = self.regioncx.get_var_name_and_span_for_region( self.infcx.tcx, self.body, - &self.local_names, + &self.local_names(), &self.upvars, errci.outlived_fr, ); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 487f78058a8c..1ad629ad167d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -399,7 +399,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { [implicit_inputs + argument_index]; let (_, span) = self.regioncx.get_argument_name_and_span_for_region( self.body, - &self.local_names, + self.local_names(), argument_index, ); @@ -973,7 +973,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { { let (arg_name, arg_span) = self.regioncx.get_argument_name_and_span_for_region( self.body, - &self.local_names, + self.local_names(), arg_index, ); let region_name = self.synthesize_region_name(); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 4d85f1090201..82b300dcb17d 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -16,7 +16,7 @@ // tidy-alphabetical-end use std::borrow::Cow; -use std::cell::RefCell; +use std::cell::{OnceCell, RefCell}; use std::marker::PhantomData; use std::ops::{ControlFlow, Deref}; @@ -391,7 +391,7 @@ fn do_mir_borrowck<'tcx>( used_mut_upvars: SmallVec::new(), borrow_set: &borrow_set, upvars: &[], - local_names: IndexVec::from_elem(None, &promoted_body.local_decls), + local_names: OnceCell::from(IndexVec::from_elem(None, &promoted_body.local_decls)), region_names: RefCell::default(), next_region_name: RefCell::new(1), polonius_output: None, @@ -414,26 +414,6 @@ fn do_mir_borrowck<'tcx>( promoted_mbcx.report_move_errors(); } - let mut local_names = IndexVec::from_elem(None, &body.local_decls); - for var_debug_info in &body.var_debug_info { - if let VarDebugInfoContents::Place(place) = var_debug_info.value { - if let Some(local) = place.as_local() { - if let Some(prev_name) = local_names[local] - && var_debug_info.name != prev_name - { - span_bug!( - var_debug_info.source_info.span, - "local {:?} has many names (`{}` vs `{}`)", - local, - prev_name, - var_debug_info.name - ); - } - local_names[local] = Some(var_debug_info.name); - } - } - } - let mut mbcx = MirBorrowckCtxt { root_cx, infcx: &infcx, @@ -450,7 +430,7 @@ fn do_mir_borrowck<'tcx>( used_mut_upvars: SmallVec::new(), borrow_set: &borrow_set, upvars: tcx.closure_captures(def), - local_names, + local_names: OnceCell::new(), region_names: RefCell::default(), next_region_name: RefCell::new(1), move_errors: Vec::new(), @@ -682,7 +662,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { upvars: &'tcx [&'tcx ty::CapturedPlace<'tcx>], /// Names of local (user) variables (extracted from `var_debug_info`). - local_names: IndexVec>, + local_names: OnceCell>>, /// Record the region names generated for each region in the given /// MIR def so that we can reuse them later in help/error messages. @@ -2610,7 +2590,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { }; // Skip over locals that begin with an underscore or have no name - if self.local_names[local].is_none_or(|name| name.as_str().starts_with('_')) { + if self.local_excluded_from_unused_mut_lint(local) { continue; } diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index d32e6f1558e4..3594c7ec2104 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -104,6 +104,8 @@ builtin_macros_concat_bytes_bad_repeat = repeat count is not a positive number builtin_macros_concat_bytes_invalid = cannot concatenate {$lit_kind} literals .byte_char = try using a byte character .byte_str = try using a byte string + .c_str = try using a null-terminated byte string + .c_str_note = concatenating C strings is ambiguous about including the '\0' .number_array = try wrapping the number in an array builtin_macros_concat_bytes_missing_literal = expected a byte literal @@ -116,10 +118,6 @@ builtin_macros_concat_bytes_oob = numeric literal is out of bounds builtin_macros_concat_bytestr = cannot concatenate a byte string literal builtin_macros_concat_c_str_lit = cannot concatenate a C string literal -builtin_macros_concat_idents_ident_args = `concat_idents!()` requires ident args - -builtin_macros_concat_idents_missing_args = `concat_idents!()` takes 1 or more arguments -builtin_macros_concat_idents_missing_comma = `concat_idents!()` expecting comma builtin_macros_concat_missing_literal = expected a literal .note = only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()` diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index ea406e706660..e75bc944d7ec 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -62,8 +62,8 @@ pub(crate) fn expand( fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span) -> Stmt { let usize = cx.path_ident(span, Ident::new(sym::usize, span)); let ty_usize = cx.ty_path(usize); - let size = Ident::from_str_and_span("size", span); - let align = Ident::from_str_and_span("align", span); + let size = Ident::new(sym::size, span); + let align = Ident::new(sym::align, span); let layout_new = cx.std_path(&[sym::alloc, sym::Layout, sym::from_size_align_unchecked]); let layout_new = cx.expr_path(cx.path(span, layout_new)); diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index dc3bb8ab52a5..df1b1eb60e18 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -652,8 +652,10 @@ mod llvm_enzyme { exprs = ecx.expr_call(new_decl_span, bb_call_expr, thin_vec![exprs]); } else { let q = QSelf { ty: d_ret_ty, path_span: span, position: 0 }; - let y = - ExprKind::Path(Some(P(q)), ecx.path_ident(span, Ident::from_str("default"))); + let y = ExprKind::Path( + Some(P(q)), + ecx.path_ident(span, Ident::with_dummy_span(kw::Default)), + ); let default_call_expr = ecx.expr(span, y); let default_call_expr = ecx.expr_call(new_decl_span, default_call_expr, thin_vec![]); diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index fe44350863c9..ec3b87467a9b 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -161,7 +161,7 @@ impl MutVisitor for CfgEval<'_> { } #[instrument(level = "trace", skip(self))] - fn visit_method_receiver_expr(&mut self, expr: &mut P) { + fn visit_method_receiver_expr(&mut self, expr: &mut ast::Expr) { self.0.configure_expr(expr, true); mut_visit::walk_expr(self, expr); } diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index 456f2b9ab31d..92d011fb9d1f 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -1,6 +1,6 @@ use rustc_ast::ptr::P; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{ExprKind, LitIntType, LitKind, UintTy, token}; +use rustc_ast::{ExprKind, LitIntType, LitKind, StrStyle, UintTy, token}; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_session::errors::report_lit_error; use rustc_span::{ErrorGuaranteed, Span}; @@ -21,15 +21,32 @@ fn invalid_type_err( let snippet = cx.sess.source_map().span_to_snippet(span).ok(); let dcx = cx.dcx(); match LitKind::from_token_lit(token_lit) { - Ok(LitKind::CStr(_, _)) => { + Ok(LitKind::CStr(_, style)) => { // Avoid ambiguity in handling of terminal `NUL` by refusing to // concatenate C string literals as bytes. - dcx.emit_err(errors::ConcatCStrLit { span }) + let sugg = if let Some(mut as_bstr) = snippet + && style == StrStyle::Cooked + && as_bstr.starts_with('c') + && as_bstr.ends_with('"') + { + // Suggest`c"foo"` -> `b"foo\0"` if we can + as_bstr.replace_range(0..1, "b"); + as_bstr.pop(); + as_bstr.push_str(r#"\0""#); + Some(ConcatBytesInvalidSuggestion::CStrLit { span, as_bstr }) + } else { + // No suggestion for a missing snippet, raw strings, or if for some reason we have + // a span that doesn't match `c"foo"` (possible if a proc macro assigns a span + // that doesn't actually point to a C string). + None + }; + // We can only provide a suggestion if we have a snip and it is not a raw string + dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "C string", sugg, cs_note: Some(()) }) } Ok(LitKind::Char(_)) => { let sugg = snippet.map(|snippet| ConcatBytesInvalidSuggestion::CharLit { span, snippet }); - dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "character", sugg }) + dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "character", sugg, cs_note: None }) } Ok(LitKind::Str(_, _)) => { // suggestion would be invalid if we are nested @@ -38,18 +55,21 @@ fn invalid_type_err( } else { None }; - dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "string", sugg }) + dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "string", sugg, cs_note: None }) } Ok(LitKind::Float(_, _)) => { - dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "float", sugg: None }) - } - Ok(LitKind::Bool(_)) => { - dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "boolean", sugg: None }) + dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "float", sugg: None, cs_note: None }) } + Ok(LitKind::Bool(_)) => dcx.emit_err(ConcatBytesInvalid { + span, + lit_kind: "boolean", + sugg: None, + cs_note: None, + }), Ok(LitKind::Int(_, _)) if !is_nested => { let sugg = snippet.map(|snippet| ConcatBytesInvalidSuggestion::IntLit { span, snippet }); - dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "numeric", sugg }) + dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "numeric", sugg, cs_note: None }) } Ok(LitKind::Int(val, LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::U8))) => { assert!(val.get() > u8::MAX.into()); // must be an error diff --git a/compiler/rustc_builtin_macros/src/concat_idents.rs b/compiler/rustc_builtin_macros/src/concat_idents.rs deleted file mode 100644 index a721f5b84c55..000000000000 --- a/compiler/rustc_builtin_macros/src/concat_idents.rs +++ /dev/null @@ -1,71 +0,0 @@ -use rustc_ast::ptr::P; -use rustc_ast::token::{self, Token}; -use rustc_ast::tokenstream::{TokenStream, TokenTree}; -use rustc_ast::{AttrVec, DUMMY_NODE_ID, Expr, ExprKind, Path, Ty, TyKind}; -use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult}; -use rustc_span::{Ident, Span, Symbol}; - -use crate::errors; - -pub(crate) fn expand_concat_idents<'cx>( - cx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: TokenStream, -) -> MacroExpanderResult<'cx> { - if tts.is_empty() { - let guar = cx.dcx().emit_err(errors::ConcatIdentsMissingArgs { span: sp }); - return ExpandResult::Ready(DummyResult::any(sp, guar)); - } - - let mut res_str = String::new(); - for (i, e) in tts.iter().enumerate() { - if i & 1 == 1 { - match e { - TokenTree::Token(Token { kind: token::Comma, .. }, _) => {} - _ => { - let guar = cx.dcx().emit_err(errors::ConcatIdentsMissingComma { span: sp }); - return ExpandResult::Ready(DummyResult::any(sp, guar)); - } - } - } else { - if let TokenTree::Token(token, _) = e { - if let Some((ident, _)) = token.ident() { - res_str.push_str(ident.name.as_str()); - continue; - } - } - - let guar = cx.dcx().emit_err(errors::ConcatIdentsIdentArgs { span: sp }); - return ExpandResult::Ready(DummyResult::any(sp, guar)); - } - } - - let ident = Ident::new(Symbol::intern(&res_str), cx.with_call_site_ctxt(sp)); - - struct ConcatIdentsResult { - ident: Ident, - } - - impl MacResult for ConcatIdentsResult { - fn make_expr(self: Box) -> Option> { - Some(P(Expr { - id: DUMMY_NODE_ID, - kind: ExprKind::Path(None, Path::from_ident(self.ident)), - span: self.ident.span, - attrs: AttrVec::new(), - tokens: None, - })) - } - - fn make_ty(self: Box) -> Option> { - Some(P(Ty { - id: DUMMY_NODE_ID, - kind: TyKind::Path(None, Path::from_ident(self.ident)), - span: self.ident.span, - tokens: None, - })) - } - } - - ExpandResult::Ready(Box::new(ConcatIdentsResult { ident })) -} diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 3a2e96a5e5af..a5ee7349fc68 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -215,6 +215,8 @@ pub(crate) struct ConcatBytesInvalid { pub(crate) lit_kind: &'static str, #[subdiagnostic] pub(crate) sugg: Option, + #[note(builtin_macros_c_str_note)] + pub(crate) cs_note: Option<()>, } #[derive(Subdiagnostic)] @@ -239,6 +241,13 @@ pub(crate) enum ConcatBytesInvalidSuggestion { span: Span, snippet: String, }, + #[note(builtin_macros_c_str_note)] + #[suggestion(builtin_macros_c_str, code = "{as_bstr}", applicability = "machine-applicable")] + CStrLit { + #[primary_span] + span: Span, + as_bstr: String, + }, #[suggestion( builtin_macros_number_array, code = "[{snippet}]", @@ -290,27 +299,6 @@ pub(crate) struct ConcatBytesBadRepeat { pub(crate) span: Span, } -#[derive(Diagnostic)] -#[diag(builtin_macros_concat_idents_missing_args)] -pub(crate) struct ConcatIdentsMissingArgs { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_concat_idents_missing_comma)] -pub(crate) struct ConcatIdentsMissingComma { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_concat_idents_ident_args)] -pub(crate) struct ConcatIdentsIdentArgs { - #[primary_span] - pub(crate) span: Span, -} - #[derive(Diagnostic)] #[diag(builtin_macros_bad_derive_target, code = E0774)] pub(crate) struct BadDeriveTarget { @@ -672,6 +660,7 @@ impl Subdiagnostic for FormatUnusedArg { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("named", self.named); let msg = diag.eagerly_translate(crate::fluent_generated::builtin_macros_format_unused_arg); + diag.remove_arg("named"); diag.span_label(self.span, msg); } } diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 39f9d5f90051..6785cb6aef5a 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -606,6 +606,7 @@ fn make_format_args( template, arguments: args, uncooked_fmt_str, + is_source_literal, })) } diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 9e7d0ec9e814..9b6dea214385 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -36,7 +36,6 @@ mod cfg_eval; mod compile_error; mod concat; mod concat_bytes; -mod concat_idents; mod define_opaque; mod derive; mod deriving; @@ -84,7 +83,6 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { compile_error: compile_error::expand_compile_error, concat: concat::expand_concat, concat_bytes: concat_bytes::expand_concat_bytes, - concat_idents: concat_idents::expand_concat_idents, const_format_args: format::expand_format_args, core_panic: edition_panic::expand_panic, env: env::expand_env, diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index daf480a9ce47..42b7e0e06d1f 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -56,7 +56,7 @@ pub fn inject( is_test_crate: bool, dcx: DiagCtxtHandle<'_>, ) { - let ecfg = ExpansionConfig::default("proc_macro".to_string(), features); + let ecfg = ExpansionConfig::default(sym::proc_macro, features); let mut cx = ExtCtxt::new(sess, ecfg, resolver, None); let mut collect = CollectProcMacros { diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index a1ee53b7ca21..682e7c9b17ae 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -36,7 +36,7 @@ pub fn inject( let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id()); let call_site = DUMMY_SP.with_call_site_ctxt(expn_id.to_expn_id()); - let ecfg = ExpansionConfig::default("std_lib_injection".to_string(), features); + let ecfg = ExpansionConfig::default(sym::std_lib_injection, features); let cx = ExtCtxt::new(sess, ecfg, resolver, None); let ident_span = if edition >= Edition2018 { span } else { call_site }; diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 0bc313cbdacb..111c85d49eb0 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -6,7 +6,7 @@ use rustc_ast as ast; use rustc_ast::entry::EntryPointType; use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; -use rustc_ast::visit::{Visitor, walk_item}; +use rustc_ast::visit::Visitor; use rustc_ast::{ModKind, attr}; use rustc_errors::DiagCtxtHandle; use rustc_expand::base::{ExtCtxt, ResolverExpand}; @@ -146,11 +146,11 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { ) = item.kind { let prev_tests = mem::take(&mut self.tests); - walk_item_kind(&mut item.kind, item.span, item.id, &mut item.vis, (), self); + ast::mut_visit::walk_item(self, item); self.add_test_cases(item.id, span, prev_tests); } else { // But in those cases, we emit a lint to warn the user of these missing tests. - walk_item(&mut InnerItemLinter { sess: self.cx.ext_cx.sess }, &item); + ast::visit::walk_item(&mut InnerItemLinter { sess: self.cx.ext_cx.sess }, &item); } } } @@ -227,7 +227,7 @@ fn generate_test_harness( panic_strategy: PanicStrategy, test_runner: Option, ) { - let econfig = ExpansionConfig::default("test".to_string(), features); + let econfig = ExpansionConfig::default(sym::test, features); let ext_cx = ExtCtxt::new(sess, econfig, resolver, None); let expn_id = ext_cx.resolver.expansion_for_ast_pass( diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index a906bec8b7e2..b893a2be9a2c 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -43,42 +43,42 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-assembler-x64" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff8e35182c7372df00447cb90a04e584e032c42b9b9b6e8c50ddaaf0d7900d5" +checksum = "f6f53499803b1607b6ee0ba0de4ba036e6da700c2e489fe8f9d0f683d0b84d31" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14220f9c2698015c3b94dc6b84ae045c1c45509ddc406e43c6139252757fdb7a" +checksum = "1aadaa5bc8430d0e7bb999459369bedd0e5816ad4a82a0e20748341c4e333eda" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d372ef2777ceefd75829e1390211ac240e9196bc60699218f7ea2419038288ee" +checksum = "2005fda2fc52a2dbce58229b4fb4483b70cbc806ba8ecc11b3f050c1a2d26cac" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56323783e423818fa89ce8078e90a3913d2a6e0810399bfce8ebd7ee87baa81f" +checksum = "56935e02452ca1249d39ad5c45a96304d0b4300a158a391fd113451e0cd4483d" [[package]] name = "cranelift-codegen" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74ffb780aab6186c6e9ba26519654b1ac55a09c0a866f6088a4efbbd84da68ed" +checksum = "62612786bf00e10999f50217d6f455d02b31591155881a45a903d1a95d1a4043" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -97,13 +97,14 @@ dependencies = [ "serde", "smallvec", "target-lexicon", + "wasmtime-math", ] [[package]] name = "cranelift-codegen-meta" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c23ef13814d3b39c869650d5961128cbbecad83fbdff4e6836a03ecf6862d7ed" +checksum = "07bae789df91ef236079733af9df11d852256c64af196f0bc6471ea0f5f301be" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -112,33 +113,33 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f623300657679f847803ce80811454bfff89cea4f6bf684be5c468d4a73631" +checksum = "1be319616d36527782558a8312508757815f64deb19b094c7b8f4337229a9bc6" [[package]] name = "cranelift-control" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f4168af69989aa6b91fab46799ed4df6096f3209f4a6c8fb4358f49c60188f" +checksum = "8810ee1ab5e9bd5cff4c0c8d240e2009cb5c2b79888fde1d5256d605712314b7" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6fa9bae1c8de26d71ac2162f069447610fd91e7780cb480ee0d76ac81eabb8" +checksum = "086452c97cfbe116bf17dbe622dc5fdf2ea97299c7d4ce42460f284387c9928a" dependencies = [ "cranelift-bitset", ] [[package]] name = "cranelift-frontend" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8219205608aa0b0e6769b580284a7e055c7e0c323c1041cde7ca078add3e412" +checksum = "4c27947010ab759330f252610c17a8cd64d123358be4f33164233d04fcd77b80" dependencies = [ "cranelift-codegen", "log", @@ -148,15 +149,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "588d0c5964f10860b04043e55aab26d7f7a206b0fd4f10c5260e8aa5773832bd" +checksum = "ec67bfb8bd55b1e9760eb9f5186dca8d81bd4d86110f8d5af01154a044c91802" [[package]] name = "cranelift-jit" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56bd917ddc524f84f4066f954062875bdfc0dffea068ee94e906d98de5ac7c33" +checksum = "d67cdfc447f2abdb46bb30a6582cce189539c3c051c1d5330692376e1400edff" dependencies = [ "anyhow", "cranelift-codegen", @@ -174,9 +175,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a03c057d8a992e06596c871341e446af43ff9224f941e5b8adea39137a5391" +checksum = "e4597eaa52bca1ed111986c7a7f70cdbe192f83d271d627201365078e37b7e84" dependencies = [ "anyhow", "cranelift-codegen", @@ -185,9 +186,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ed3c94cb97b14f92b6a94a1d45ef8c851f6a2ad9114e5d91d233f7da638fed" +checksum = "75a9b63edea46e013fce459c46e500462cb03a0490fdd9c18fe42b1dd7b93aa1" dependencies = [ "cranelift-codegen", "libc", @@ -196,9 +197,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64dacef362a69375a604f6636e5e9a174fb96dba3b273646fcd9fa85c1d0997" +checksum = "ce706f0166d5b7f31693dff521e87cb9858e12adf22ffcde93c4a2826f8f04a9" dependencies = [ "anyhow", "cranelift-codegen", @@ -211,9 +212,9 @@ dependencies = [ [[package]] name = "cranelift-srcgen" -version = "0.120.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85256fac1519a7d25a040c1d850fba67478f3f021ad5fdf738ba4425ee862dbf" +checksum = "7d5870e266df8237b56cc98b04f5739c228565c92dd629ec6c66efa87271a158" [[package]] name = "crc32fast" @@ -288,6 +289,12 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + [[package]] name = "log" version = "0.4.22" @@ -446,9 +453,9 @@ checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "wasmtime-jit-icache-coherence" -version = "33.0.0" +version = "34.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175e924dbc944c185808466d1e90b5a7feb610f3b9abdfe26f8ee25fd1086d1c" +checksum = "2eedc0324e37cf39b049f4dca0c30997eaab49f09006d5f4c1994e64e7b7dba8" dependencies = [ "anyhow", "cfg-if", @@ -456,6 +463,15 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "wasmtime-math" +version = "34.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd35fae4cf51d2b4a9bd2ef04b0eb309fa1849cab6a6ab5ac27cbd054ea284d" +dependencies = [ + "libm", +] + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 94fcbd0a5023..9066e4dbbb52 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.120.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } -cranelift-frontend = { version = "0.120.0" } -cranelift-module = { version = "0.120.0" } -cranelift-native = { version = "0.120.0" } -cranelift-jit = { version = "0.120.0", optional = true } -cranelift-object = { version = "0.120.0" } +cranelift-codegen = { version = "0.121.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.121.0" } +cranelift-module = { version = "0.121.0" } +cranelift-native = { version = "0.121.0" } +cranelift-jit = { version = "0.121.0", optional = true } +cranelift-object = { version = "0.121.0" } target-lexicon = "0.13" gimli = { version = "0.31", default-features = false, features = ["write"] } object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } @@ -24,12 +24,12 @@ smallvec = "1.8.1" [patch.crates-io] # Uncomment to use an unreleased version of cranelift -#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-33.0.0", version = "0.120.0" } -#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-33.0.0", version = "0.120.0" } -#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-33.0.0", version = "0.120.0" } -#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-33.0.0", version = "0.120.0" } -#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-33.0.0", version = "0.120.0" } -#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-33.0.0", version = "0.120.0" } +#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" } +#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" } +#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" } +#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" } +#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" } +#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" } # Uncomment to use local checkout of cranelift #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs index 674acfbd3097..43025137bc6b 100644 --- a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs +++ b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs @@ -6,8 +6,8 @@ use crate::{CodegenBackend, SysrootKind, build_sysroot}; static ABI_CAFE_REPO: GitRepo = GitRepo::github( "Gankra", "abi-cafe", - "f1220cfd13b57f5c0082c26529163865ee25e115", - "fe93a9acd461425d", + "94d38030419eb00a1ba80e5e2b4d763dcee58db4", + "6efb4457893c8670", "abi-cafe", ); @@ -46,6 +46,10 @@ pub(crate) fn run( let mut cmd = ABI_CAFE.run(bootstrap_host_compiler, dirs); cmd.arg("--"); + cmd.arg("--debug"); + + cmd.arg("--rules").arg(dirs.source_dir.join("scripts/abi-cafe-rules.toml")); + // stdcall, vectorcall and such don't work yet cmd.arg("--conventions").arg("c").arg("--conventions").arg("rust"); diff --git a/compiler/rustc_codegen_cranelift/patches/0002-abi-cafe-Disable-broken-tests.patch b/compiler/rustc_codegen_cranelift/patches/0002-abi-cafe-Disable-broken-tests.patch deleted file mode 100644 index 01b6a990b720..000000000000 --- a/compiler/rustc_codegen_cranelift/patches/0002-abi-cafe-Disable-broken-tests.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 236df390f3bc4ed69c26f4d51d584bea246da886 Mon Sep 17 00:00:00 2001 -From: bjorn3 <17426603+bjorn3@users.noreply.github.com> -Date: Tue, 9 Jul 2024 11:25:14 +0000 -Subject: [PATCH] Disable broken tests - ---- - src/report.rs | 36 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 36 insertions(+) - -diff --git a/src/toolchains/rust.rs b/src/toolchains/rust.rs -index 0c50f7a..bfde2b1 100644 ---- a/src/toolchains/rust.rs -+++ b/src/toolchains/rust.rs -@@ -83,6 +83,7 @@ impl Toolchain for RustcToolchain { - .arg(out_dir) - .arg("--target") - .arg(built_info::TARGET) -+ .arg("-g") - .arg(format!("-Cmetadata={lib_name}")) - .arg(src_path); - if let Some(codegen_backend) = &self.codegen_backend { -diff --git a/src/report.rs b/src/report.rs -index 958ab43..dcf1044 100644 ---- a/src/report.rs -+++ b/src/report.rs -@@ -48,6 +48,40 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn Toolchain, callee: &dyn Toolc - // - // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES - -+ if cfg!(all(target_arch = "aarch64", target_os = "linux")) { -+ if test.test == "F32Array" && test.options.convention == CallingConvention::C { -+ result.check = Busted(Check); -+ } -+ } -+ -+ if cfg!(all(target_arch = "aarch64", target_os = "macos")) { -+ if test.test == "SingleVariantUnion" && test.options.convention == CallingConvention::C && test.options.repr == LangRepr::C { -+ result.check = Busted(Check); -+ } -+ -+ if test.test == "OptionU128" && test.caller == "rustc" && test.options.convention == CallingConvention::Rust && test.options.repr == LangRepr::C { -+ result.check = Busted(Run); -+ } -+ -+ if test.test == "OptionU128" && test.caller == "cgclif" && test.options.convention == CallingConvention::Rust && test.options.repr == LangRepr::C { -+ result.check = Busted(Check); -+ } -+ } -+ -+ if cfg!(all(target_arch = "x86_64", windows)) { -+ if test.test == "simple" && test.options.convention == CallingConvention::Rust { -+ result.check = Busted(Check); -+ } -+ -+ if test.test == "simple" && test.options.convention == CallingConvention::Rust && test.caller == "rustc" { -+ result.check = Busted(Run); -+ } -+ } -+ -+ if test.test == "f16" || test.test == "f128" { -+ result.run = Skip; -+ } -+ - // END OF VENDOR RESERVED AREA - // - // --- -2.34.1 - diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index af4bd6dc6b85..150bb562f74a 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-05-25" +channel = "nightly-2025-06-24" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" diff --git a/compiler/rustc_codegen_cranelift/scripts/abi-cafe-rules.toml b/compiler/rustc_codegen_cranelift/scripts/abi-cafe-rules.toml new file mode 100644 index 000000000000..54f9445c8e52 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/scripts/abi-cafe-rules.toml @@ -0,0 +1,17 @@ +[target.'cfg(all(target_arch = "aarch64", target_os = "linux"))'] +'F32Array::conv_c'.busted = "check" + +[target.'cfg(all(target_arch = "aarch64", target_os = "macos"))'] +'SingleVariantUnion::conv_c::repr_c'.busted = "check" +'OptionU128::conv_rust::repr_c::rustc_caller'.busted = "run" +'OptionU128::conv_rust::repr_c::cgclif_caller'.busted = "check" + +[target.'cfg(all(target_arch = "x86_64", windows))'] +'simple::conv_rust'.busted = "check" +'simple::conv_rust::rustc_caller'.busted = "run" + +[target.'*'.'f16'] +run = "skip" + +[target.'*'.'f128'] +run = "skip" diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index 32c71f433b0f..7e356b4b462b 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -151,20 +151,6 @@ rm tests/ui/process/process-panic-after-fork.rs # same cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist cat <( crate::pointer::Pointer::new(global_ptr) } -pub(crate) fn data_id_for_alloc_id( +fn data_id_for_alloc_id( cx: &mut ConstantCx, module: &mut dyn Module, alloc_id: AllocId, diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index 615f6c47d902..37fbe4be1b0f 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -202,9 +202,10 @@ pub(super) fn codegen_x86_llvm_intrinsic_call<'tcx>( }; let x = codegen_operand(fx, &x.node); let y = codegen_operand(fx, &y.node); - let kind = match &kind.node { - Operand::Constant(const_) => crate::constant::eval_mir_constant(fx, const_).0, - Operand::Copy(_) | Operand::Move(_) => unreachable!("{kind:?}"), + let kind = if let Some(const_) = kind.node.constant() { + crate::constant::eval_mir_constant(fx, const_).0 + } else { + unreachable!("{kind:?}") }; let flt_cc = match kind diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 46a441488fa6..68ff0b622c8f 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -205,9 +205,10 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // Find a way to reuse `immediate_const_vector` from `codegen_ssa` instead. let indexes = { use rustc_middle::mir::interpret::*; - let idx_const = match &idx.node { - Operand::Constant(const_) => crate::constant::eval_mir_constant(fx, const_).0, - Operand::Copy(_) | Operand::Move(_) => unreachable!("{idx:?}"), + let idx_const = if let Some(const_) = idx.node.constant() { + crate::constant::eval_mir_constant(fx, const_).0 + } else { + unreachable!("{idx:?}") }; let idx_bytes = match idx_const { diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 07ea29f3024e..8e34436fb5e0 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -184,7 +184,7 @@ impl CodegenBackend for CraneliftCodegenBackend { // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)] let target_features = if sess.target.arch == "x86_64" && sess.target.os != "none" { // x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled - vec![sym::fsxr, sym::sse, sym::sse2, Symbol::intern("x87")] + vec![sym::fxsr, sym::sse, sym::sse2, Symbol::intern("x87")] } else if sess.target.arch == "aarch64" { match &*sess.target.os { "none" => vec![], diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl index 18a8a5a1e048..55a28bc9493e 100644 --- a/compiler/rustc_codegen_gcc/messages.ftl +++ b/compiler/rustc_codegen_gcc/messages.ftl @@ -1,7 +1,3 @@ -codegen_gcc_unknown_ctarget_feature_prefix = - unknown feature specified for `-Ctarget-feature`: `{$feature}` - .note = features must begin with a `+` to enable or `-` to disable it - codegen_gcc_unwinding_inline_asm = GCC backend does not support unwinding from inline asm @@ -16,15 +12,3 @@ codegen_gcc_lto_disallowed = lto can only be run for executables, cdylibs and st codegen_gcc_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto` codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err}) - -codegen_gcc_unknown_ctarget_feature = - unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}` - .note = it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future - .possible_feature = you might have meant: `{$rust_feature}` - .consider_filing_feature_request = consider filing a feature request - -codegen_gcc_missing_features = - add the missing features in a `target_feature` attribute - -codegen_gcc_target_feature_disable_or_enable = - the target features {$features} must all be either enabled or disabled together diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index a2e34d1f8fbc..7852aebe0c23 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1591,9 +1591,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { (value1, value2) } - fn filter_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { + fn filter_landing_pad(&mut self, pers_fn: RValue<'gcc>) { // TODO(antoyo): generate the correct landing pad - self.cleanup_landing_pad(pers_fn) + self.cleanup_landing_pad(pers_fn); } #[cfg(feature = "master")] diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 7786be9ae5de..b7e7343460fb 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -1,30 +1,6 @@ -use rustc_macros::{Diagnostic, Subdiagnostic}; +use rustc_macros::Diagnostic; use rustc_span::Span; -#[derive(Diagnostic)] -#[diag(codegen_gcc_unknown_ctarget_feature_prefix)] -#[note] -pub(crate) struct UnknownCTargetFeaturePrefix<'a> { - pub feature: &'a str, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_unknown_ctarget_feature)] -#[note] -pub(crate) struct UnknownCTargetFeature<'a> { - pub feature: &'a str, - #[subdiagnostic] - pub rust_feature: PossibleFeature<'a>, -} - -#[derive(Subdiagnostic)] -pub(crate) enum PossibleFeature<'a> { - #[help(codegen_gcc_possible_feature)] - Some { rust_feature: &'a str }, - #[help(codegen_gcc_consider_filing_feature_request)] - None, -} - #[derive(Diagnostic)] #[diag(codegen_gcc_unwinding_inline_asm)] pub(crate) struct UnwindingInlineAsm { diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 2e00d5fcb612..42ba40692b75 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -1,20 +1,12 @@ #[cfg(feature = "master")] use gccjit::Context; -use rustc_codegen_ssa::codegen_attrs::check_tied_features; -use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::unord::UnordSet; +use rustc_codegen_ssa::target_features; use rustc_session::Session; -use rustc_session::features::{StabilityExt, retpoline_features_by_flags}; -use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; use smallvec::{SmallVec, smallvec}; -use crate::errors::{PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix}; - -fn gcc_features_by_flags(sess: &Session) -> Vec<&str> { - let mut features: Vec<&str> = Vec::new(); - retpoline_features_by_flags(sess, &mut features); - features +fn gcc_features_by_flags(sess: &Session, features: &mut Vec) { + target_features::retpoline_features_by_flags(sess, features); + // FIXME: LLVM also sets +reserve-x18 here under some conditions. } /// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, @@ -44,98 +36,29 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec. - all_rust_features.push((false, feature)); - } else if !feature.is_empty() && diagnostics { - sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature }); - } - } - // Remove features that are meant for rustc, not codegen. - all_rust_features.retain(|&(_, feature)| { - // Retain if it is not a rustc feature - !RUSTC_SPECIFIC_FEATURES.contains(&feature) - }); - - // Check feature validity. - if diagnostics { - for &(enable, feature) in &all_rust_features { - let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature); - match feature_state { - None => { - let rust_feature = known_features.iter().find_map(|&(rust_feature, _, _)| { - let gcc_features = to_gcc_features(sess, rust_feature); - if gcc_features.contains(&feature) && !gcc_features.contains(&rust_feature) - { - Some(rust_feature) - } else { - None - } - }); - let unknown_feature = if let Some(rust_feature) = rust_feature { - UnknownCTargetFeature { - feature, - rust_feature: PossibleFeature::Some { rust_feature }, - } - } else { - UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None } - }; - sess.dcx().emit_warn(unknown_feature); - } - Some(&(_, stability, _)) => { - stability.verify_feature_enabled_by_flag(sess, enable, feature); - } - } - - // FIXME(nagisa): figure out how to not allocate a full hashset here. - featsmap.insert(feature, enable); - } - } - - // Translate this into GCC features. - let feats = - all_rust_features.iter().flat_map(|&(enable, feature)| { - let enable_disable = if enable { '+' } else { '-' }; + target_features::flag_to_backend_features( + sess, + diagnostics, + |feature| to_gcc_features(sess, feature), + |feature, enable| { // We run through `to_gcc_features` when // passing requests down to GCC. This means that all in-language // features also work on the command line instead of having two // different names when the GCC name and the Rust name differ. - to_gcc_features(sess, feature) - .iter() - .flat_map(|feat| to_gcc_features(sess, feat).into_iter()) - .map(|feature| { - if enable_disable == '-' { - format!("-{}", feature) - } else { - feature.to_string() - } - }) - .collect::>() - }); - features.extend(feats); + features.extend( + to_gcc_features(sess, feature) + .iter() + .flat_map(|feat| to_gcc_features(sess, feat).into_iter()) + .map( + |feature| { + if !enable { format!("-{}", feature) } else { feature.to_string() } + }, + ), + ); + }, + ); - if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) { - sess.dcx().emit_err(TargetFeatureDisableOrEnable { - features: f, - span: None, - missing_features: None, - }); - } + gcc_features_by_flags(sess, &mut features); features } diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index aa57655921d4..a912678ef2a1 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -102,6 +102,7 @@ use rustc_codegen_ssa::back::write::{ CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn, }; use rustc_codegen_ssa::base::codegen_crate; +use rustc_codegen_ssa::target_features::cfg_target_feature; use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods}; use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig}; use rustc_data_structures::fx::FxIndexMap; @@ -476,42 +477,21 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { /// Returns the features that should be set in `cfg(target_feature)`. fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig { - // TODO(antoyo): use global_gcc_features. - let f = |allow_unstable| { - sess.target - .rust_target_features() - .iter() - .filter_map(|&(feature, gate, _)| { - if allow_unstable - || (gate.in_cfg() - && (sess.is_nightly_build() || gate.requires_nightly().is_none())) - { - Some(feature) - } else { - None - } - }) - .filter(|feature| { - // TODO: we disable Neon for now since we don't support the LLVM intrinsics for it. - if *feature == "neon" { - return false; - } - target_info.cpu_supports(feature) - // cSpell:disable - /* - adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma, - avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq, - bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm, - sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves - */ - // cSpell:enable - }) - .map(Symbol::intern) - .collect() - }; - - let target_features = f(false); - let unstable_target_features = f(true); + let (unstable_target_features, target_features) = cfg_target_feature(sess, |feature| { + // TODO: we disable Neon for now since we don't support the LLVM intrinsics for it. + if feature == "neon" { + return false; + } + target_info.cpu_supports(feature) + // cSpell:disable + /* + adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma, + avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq, + bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm, + sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves + */ + // cSpell:enable + }); let has_reliable_f16 = target_info.supports_target_dependent_type(CType::Float16); let has_reliable_f128 = target_info.supports_target_dependent_type(CType::Float128); diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index 3faeb9b3b221..3885f18271f1 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -59,16 +59,6 @@ codegen_llvm_symbol_already_defined = codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple} codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err} -codegen_llvm_unknown_ctarget_feature = - unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}` - .note = it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future - .possible_feature = you might have meant: `{$rust_feature}` - .consider_filing_feature_request = consider filing a feature request - -codegen_llvm_unknown_ctarget_feature_prefix = - unknown feature specified for `-Ctarget-feature`: `{$feature}` - .note = features must begin with a `+` to enable or `-` to disable it - codegen_llvm_unknown_debuginfo_compression = unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err} diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 27fd09745ff0..adb53e0b66c2 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -491,11 +491,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx); attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]); } - // function alignment can be set globally with the `-Zmin-function-alignment=` flag; - // the alignment from a `#[repr(align())]` is used if it specifies a higher alignment. - if let Some(align) = - Ord::max(cx.tcx.sess.opts.unstable_opts.min_function_alignment, codegen_fn_attrs.alignment) - { + if let Some(align) = codegen_fn_attrs.alignment { llvm::set_alignment(llfn, align); } if let Some(backchain) = backchain_attr(cx) { diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index ee46b49a094c..9c62244f3c9f 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -587,7 +587,7 @@ fn thin_lto( } fn enable_autodiff_settings(ad: &[config::AutoDiff]) { - for &val in ad { + for val in ad { // We intentionally don't use a wildcard, to not forget handling anything new. match val { config::AutoDiff::PrintPerf => { @@ -599,6 +599,10 @@ fn enable_autodiff_settings(ad: &[config::AutoDiff]) { config::AutoDiff::PrintTA => { llvm::set_print_type(true); } + config::AutoDiff::PrintTAFn(fun) => { + llvm::set_print_type(true); // Enable general type printing + llvm::set_print_type_fun(&fun); // Set specific function to analyze + } config::AutoDiff::Inline => { llvm::set_inline(true); } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 5e9594dd06bb..d0aa7320b4b6 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1166,11 +1166,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { (self.extract_value(landing_pad, 0), self.extract_value(landing_pad, 1)) } - fn filter_landing_pad(&mut self, pers_fn: &'ll Value) -> (&'ll Value, &'ll Value) { + fn filter_landing_pad(&mut self, pers_fn: &'ll Value) { let ty = self.type_struct(&[self.type_ptr(), self.type_i32()], false); let landing_pad = self.landing_pad(ty, pers_fn, 1); self.add_clause(landing_pad, self.const_array(self.type_ptr(), &[])); - (self.extract_value(landing_pad, 0), self.extract_value(landing_pad, 1)) } fn resume(&mut self, exn0: &'ll Value, exn1: &'ll Value) { diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 8bc74fbec7ec..d50ad8a1a9cb 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -3,35 +3,11 @@ use std::path::Path; use rustc_data_structures::small_c_str::SmallCStr; use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level}; -use rustc_macros::{Diagnostic, Subdiagnostic}; +use rustc_macros::Diagnostic; use rustc_span::Span; use crate::fluent_generated as fluent; -#[derive(Diagnostic)] -#[diag(codegen_llvm_unknown_ctarget_feature_prefix)] -#[note] -pub(crate) struct UnknownCTargetFeaturePrefix<'a> { - pub feature: &'a str, -} - -#[derive(Diagnostic)] -#[diag(codegen_llvm_unknown_ctarget_feature)] -#[note] -pub(crate) struct UnknownCTargetFeature<'a> { - pub feature: &'a str, - #[subdiagnostic] - pub rust_feature: PossibleFeature<'a>, -} - -#[derive(Subdiagnostic)] -pub(crate) enum PossibleFeature<'a> { - #[help(codegen_llvm_possible_feature)] - Some { rust_feature: &'a str }, - #[help(codegen_llvm_consider_filing_feature_request)] - None, -} - #[derive(Diagnostic)] #[diag(codegen_llvm_symbol_already_defined)] pub(crate) struct SymbolAlreadyDefined<'a> { diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs index 2ad39fc85381..b94716b89d61 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs @@ -57,14 +57,19 @@ pub(crate) use self::Enzyme_AD::*; #[cfg(llvm_enzyme)] pub(crate) mod Enzyme_AD { + use std::ffi::{CString, c_char}; + use libc::c_void; + unsafe extern "C" { pub(crate) fn EnzymeSetCLBool(arg1: *mut ::std::os::raw::c_void, arg2: u8); + pub(crate) fn EnzymeSetCLString(arg1: *mut ::std::os::raw::c_void, arg2: *const c_char); } unsafe extern "C" { static mut EnzymePrintPerf: c_void; static mut EnzymePrintActivity: c_void; static mut EnzymePrintType: c_void; + static mut EnzymeFunctionToAnalyze: c_void; static mut EnzymePrint: c_void; static mut EnzymeStrictAliasing: c_void; static mut looseTypeAnalysis: c_void; @@ -86,6 +91,15 @@ pub(crate) mod Enzyme_AD { EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintType), print as u8); } } + pub(crate) fn set_print_type_fun(fun_name: &str) { + let c_fun_name = CString::new(fun_name).unwrap(); + unsafe { + EnzymeSetCLString( + std::ptr::addr_of_mut!(EnzymeFunctionToAnalyze), + c_fun_name.as_ptr() as *const c_char, + ); + } + } pub(crate) fn set_print(print: bool) { unsafe { EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrint), print as u8); @@ -132,6 +146,9 @@ pub(crate) mod Fallback_AD { pub(crate) fn set_print_type(print: bool) { unimplemented!() } + pub(crate) fn set_print_type_fun(fun_name: &str) { + unimplemented!() + } pub(crate) fn set_print(print: bool) { unimplemented!() } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 0e77bc43df80..6fd07d562afd 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -6,27 +6,20 @@ use std::sync::Once; use std::{ptr, slice, str}; use libc::c_int; -use rustc_codegen_ssa::TargetConfig; use rustc_codegen_ssa::base::wants_wasm_eh; -use rustc_codegen_ssa::codegen_attrs::check_tied_features; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_codegen_ssa::target_features::cfg_target_feature; +use rustc_codegen_ssa::{TargetConfig, target_features}; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_data_structures::unord::UnordSet; use rustc_fs_util::path_to_c_string; use rustc_middle::bug; use rustc_session::Session; use rustc_session::config::{PrintKind, PrintRequest}; -use rustc_session::features::{StabilityExt, retpoline_features_by_flags}; -use rustc_span::Symbol; use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport}; -use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES}; use smallvec::{SmallVec, smallvec}; use crate::back::write::create_informational_target_machine; -use crate::errors::{ - FixedX18InvalidArch, PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix, -}; -use crate::llvm; +use crate::{errors, llvm}; static INIT: Once = Once::new(); @@ -195,15 +188,6 @@ impl<'a> LLVMFeature<'a> { ) -> Self { Self { llvm_feature_name, dependencies } } - - fn contains(&'a self, feat: &str) -> bool { - self.iter().any(|dep| dep == feat) - } - - fn iter(&'a self) -> impl Iterator { - let dependencies = self.dependencies.iter().map(|feat| feat.as_str()); - std::iter::once(self.llvm_feature_name).chain(dependencies) - } } impl<'a> IntoIterator for LLVMFeature<'a> { @@ -216,18 +200,22 @@ impl<'a> IntoIterator for LLVMFeature<'a> { } } -// WARNING: the features after applying `to_llvm_features` must be known -// to LLVM or the feature detection code will walk past the end of the feature -// array, leading to crashes. -// -// To find a list of LLVM's names, see llvm-project/llvm/lib/Target/{ARCH}/*.td -// where `{ARCH}` is the architecture name. Look for instances of `SubtargetFeature`. -// -// Check the current rustc fork of LLVM in the repo at https://github.com/rust-lang/llvm-project/. -// The commit in use can be found via the `llvm-project` submodule in -// https://github.com/rust-lang/rust/tree/master/src Though note that Rust can also be build with -// an external precompiled version of LLVM which might lead to failures if the oldest tested / -// supported LLVM version doesn't yet support the relevant intrinsics. +/// Convert a Rust feature name to an LLVM feature name. Returning `None` means the +/// feature should be skipped, usually because it is not supported by the current +/// LLVM version. +/// +/// WARNING: the features after applying `to_llvm_features` must be known +/// to LLVM or the feature detection code will walk past the end of the feature +/// array, leading to crashes. +/// +/// To find a list of LLVM's names, see llvm-project/llvm/lib/Target/{ARCH}/*.td +/// where `{ARCH}` is the architecture name. Look for instances of `SubtargetFeature`. +/// +/// Check the current rustc fork of LLVM in the repo at +/// . The commit in use can be found via the +/// `llvm-project` submodule in Though note that +/// Rust can also be build with an external precompiled version of LLVM which might lead to failures +/// if the oldest tested / supported LLVM version doesn't yet support the relevant intrinsics. pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option> { let arch = if sess.target.arch == "x86_64" { "x86" @@ -343,98 +331,25 @@ pub(crate) fn target_config(sess: &Session) -> TargetConfig { // the target CPU, that is still expanded to target features (with all their implied features) // by LLVM. let target_machine = create_informational_target_machine(sess, true); - // Compute which of the known target features are enabled in the 'base' target machine. We only - // consider "supported" features; "forbidden" features are not reflected in `cfg` as of now. - let mut features: FxHashSet = sess - .target - .rust_target_features() - .iter() - .filter(|(feature, _, _)| { - // skip checking special features, as LLVM may not understand them - if RUSTC_SPECIAL_FEATURES.contains(feature) { - return true; - } - if let Some(feat) = to_llvm_features(sess, feature) { - for llvm_feature in feat { - let cstr = SmallCStr::new(llvm_feature); - // `LLVMRustHasFeature` is moderately expensive. On targets with many - // features (e.g. x86) these calls take a non-trivial fraction of runtime - // when compiling very small programs. - if !unsafe { llvm::LLVMRustHasFeature(target_machine.raw(), cstr.as_ptr()) } { - return false; - } + + let (unstable_target_features, target_features) = cfg_target_feature(sess, |feature| { + if let Some(feat) = to_llvm_features(sess, feature) { + // All the LLVM features this expands to must be enabled. + for llvm_feature in feat { + let cstr = SmallCStr::new(llvm_feature); + // `LLVMRustHasFeature` is moderately expensive. On targets with many + // features (e.g. x86) these calls take a non-trivial fraction of runtime + // when compiling very small programs. + if !unsafe { llvm::LLVMRustHasFeature(target_machine.raw(), cstr.as_ptr()) } { + return false; } - true - } else { - false } - }) - .map(|(feature, _, _)| Symbol::intern(feature)) - .collect(); - - // Add enabled and remove disabled features. - for (enabled, feature) in - sess.opts.cg.target_feature.split(',').filter_map(|s| match s.chars().next() { - Some('+') => Some((true, Symbol::intern(&s[1..]))), - Some('-') => Some((false, Symbol::intern(&s[1..]))), - _ => None, - }) - { - if enabled { - // Also add all transitively implied features. - - // We don't care about the order in `features` since the only thing we use it for is the - // `features.contains` below. - #[allow(rustc::potential_query_instability)] - features.extend( - sess.target - .implied_target_features(feature.as_str()) - .iter() - .map(|s| Symbol::intern(s)), - ); + true } else { - // Remove transitively reverse-implied features. - - // We don't care about the order in `features` since the only thing we use it for is the - // `features.contains` below. - #[allow(rustc::potential_query_instability)] - features.retain(|f| { - if sess.target.implied_target_features(f.as_str()).contains(&feature.as_str()) { - // If `f` if implies `feature`, then `!feature` implies `!f`, so we have to - // remove `f`. (This is the standard logical contraposition principle.) - false - } else { - // We can keep `f`. - true - } - }); + false } - } + }); - // Filter enabled features based on feature gates. - let f = |allow_unstable| { - sess.target - .rust_target_features() - .iter() - .filter_map(|(feature, gate, _)| { - // The `allow_unstable` set is used by rustc internally to determined which target - // features are truly available, so we want to return even perma-unstable - // "forbidden" features. - if allow_unstable - || (gate.in_cfg() - && (sess.is_nightly_build() || gate.requires_nightly().is_none())) - { - Some(Symbol::intern(feature)) - } else { - None - } - }) - .filter(|feature| features.contains(&feature)) - .collect() - }; - - let target_features = f(false); - let unstable_target_features = f(true); let mut cfg = TargetConfig { target_features, unstable_target_features, @@ -707,10 +622,18 @@ pub(crate) fn target_cpu(sess: &Session) -> &str { handle_native(cpu_name) } -fn llvm_features_by_flags(sess: &Session) -> Vec<&str> { - let mut features: Vec<&str> = Vec::new(); - retpoline_features_by_flags(sess, &mut features); - features +/// The target features for compiler flags other than `-Ctarget-features`. +fn llvm_features_by_flags(sess: &Session, features: &mut Vec) { + target_features::retpoline_features_by_flags(sess, features); + + // -Zfixed-x18 + if sess.opts.unstable_opts.fixed_x18 { + if sess.target.arch != "aarch64" { + sess.dcx().emit_fatal(errors::FixedX18InvalidArch { arch: &sess.target.arch }); + } else { + features.push("+reserve-x18".into()); + } + } } /// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, @@ -777,6 +700,8 @@ pub(crate) fn global_llvm_features( .split(',') .filter(|v| !v.is_empty()) // Drop +v8plus feature introduced in LLVM 20. + // (Hard-coded target features do not go through `to_llvm_feature` since they already + // are LLVM feature names, hence we need a special case here.) .filter(|v| *v != "+v8plus" || get_version() >= (20, 0, 0)) .map(String::from), ); @@ -787,86 +712,23 @@ pub(crate) fn global_llvm_features( // -Ctarget-features if !only_base_features { - let known_features = sess.target.rust_target_features(); - // Will only be filled when `diagnostics` is set! - let mut featsmap = FxHashMap::default(); - - // Compute implied features - let mut all_rust_features = vec![]; - for feature in sess.opts.cg.target_feature.split(',').chain(llvm_features_by_flags(sess)) { - if let Some(feature) = feature.strip_prefix('+') { - all_rust_features.extend( - UnordSet::from(sess.target.implied_target_features(feature)) - .to_sorted_stable_ord() - .iter() - .map(|&&s| (true, s)), - ) - } else if let Some(feature) = feature.strip_prefix('-') { - // FIXME: Why do we not remove implied features on "-" here? - // We do the equivalent above in `target_config`. - // See . - all_rust_features.push((false, feature)); - } else if !feature.is_empty() { - if diagnostics { - sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature }); - } - } - } - // Remove features that are meant for rustc, not LLVM. - all_rust_features.retain(|(_, feature)| { - // Retain if it is not a rustc feature - !RUSTC_SPECIFIC_FEATURES.contains(feature) - }); - - // Check feature validity. - if diagnostics { - for &(enable, feature) in &all_rust_features { - let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature); - match feature_state { - None => { - let rust_feature = - known_features.iter().find_map(|&(rust_feature, _, _)| { - let llvm_features = to_llvm_features(sess, rust_feature)?; - if llvm_features.contains(feature) - && !llvm_features.contains(rust_feature) - { - Some(rust_feature) - } else { - None - } - }); - let unknown_feature = if let Some(rust_feature) = rust_feature { - UnknownCTargetFeature { - feature, - rust_feature: PossibleFeature::Some { rust_feature }, - } - } else { - UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None } - }; - sess.dcx().emit_warn(unknown_feature); - } - Some((_, stability, _)) => { - stability.verify_feature_enabled_by_flag(sess, enable, feature); - } - } - - // FIXME(nagisa): figure out how to not allocate a full hashset here. - featsmap.insert(feature, enable); - } - } - - // Translate this into LLVM features. - let feats = all_rust_features - .iter() - .filter_map(|&(enable, feature)| { + target_features::flag_to_backend_features( + sess, + diagnostics, + |feature| { + to_llvm_features(sess, feature) + .map(|f| SmallVec::<[&str; 2]>::from_iter(f.into_iter())) + .unwrap_or_default() + }, + |feature, enable| { let enable_disable = if enable { '+' } else { '-' }; // We run through `to_llvm_features` when // passing requests down to LLVM. This means that all in-language // features also work on the command line instead of having two // different names when the LLVM name and the Rust name differ. - let llvm_feature = to_llvm_features(sess, feature)?; + let Some(llvm_feature) = to_llvm_features(sess, feature) else { return }; - Some( + features.extend( std::iter::once(format!( "{}{}", enable_disable, llvm_feature.llvm_feature_name @@ -881,27 +743,12 @@ pub(crate) fn global_llvm_features( }, )), ) - }) - .flatten(); - features.extend(feats); - - if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) { - sess.dcx().emit_err(rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable { - features: f, - span: None, - missing_features: None, - }); - } + }, + ); } - // -Zfixed-x18 - if sess.opts.unstable_opts.fixed_x18 { - if sess.target.arch != "aarch64" { - sess.dcx().emit_fatal(FixedX18InvalidArch { arch: &sess.target.arch }); - } else { - features.push("+reserve-x18".into()); - } - } + // We add this in the "base target" so that these show up in `sess.unstable_target_features`. + llvm_features_by_flags(sess, &mut features); features } diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 5322fe58cf33..b2e86414d902 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -48,8 +48,6 @@ codegen_ssa_error_writing_def_file = codegen_ssa_expected_name_value_pair = expected name value pair -codegen_ssa_expected_one_argument = expected one argument - codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified @@ -68,6 +66,11 @@ codegen_ssa_failed_to_write = failed to write {$path}: {$error} codegen_ssa_field_associated_value_expected = associated value expected for `{$name}` +codegen_ssa_forbidden_ctarget_feature = + target feature `{$feature}` cannot be {$enabled} with `-Ctarget-feature`: {$reason} + .note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +codegen_ssa_forbidden_ctarget_feature_issue = for more information, see issue #116344 + codegen_ssa_forbidden_target_feature_attr = target feature `{$feature}` cannot be enabled with `#[target_feature]`: {$reason} @@ -86,9 +89,6 @@ codegen_ssa_incorrect_cgu_reuse_type = codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient. -codegen_ssa_invalid_argument = invalid argument - .help = valid inline arguments are `always` and `never` - codegen_ssa_invalid_instruction_set = invalid instruction set specified codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]` @@ -221,6 +221,8 @@ codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple time codegen_ssa_no_field = no field `{$name}` +codegen_ssa_no_mangle_nameless = `#[no_mangle]` cannot be used on {$definition} as it has no name + codegen_ssa_no_module_named = no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names} @@ -368,8 +370,22 @@ codegen_ssa_unexpected_parameter_name = unexpected parameter name codegen_ssa_unknown_archive_kind = Don't know how to build archive of type: {$kind} +codegen_ssa_unknown_ctarget_feature = + unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}` + .note = it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future + .possible_feature = you might have meant: `{$rust_feature}` + .consider_filing_feature_request = consider filing a feature request + +codegen_ssa_unknown_ctarget_feature_prefix = + unknown feature specified for `-Ctarget-feature`: `{$feature}` + .note = features must begin with a `+` to enable or `-` to disable it + codegen_ssa_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified +codegen_ssa_unstable_ctarget_feature = + unstable feature specified for `-Ctarget-feature`: `{$feature}` + .note = this feature is not stably supported; its behavior can change in the future + codegen_ssa_unsupported_instruction_set = target does not support `#[instruction_set]` codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8882ba359b77..4a2425967e4f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -865,7 +865,7 @@ fn link_natively( command: cmd, escaped_output, verbose: sess.opts.verbose, - sysroot_dir: sess.sysroot.clone(), + sysroot_dir: sess.opts.sysroot.path().to_owned(), }; sess.dcx().emit_err(err); // If MSVC's `link.exe` was expected but the return code @@ -1249,10 +1249,10 @@ fn link_sanitizer_runtime( if path.exists() { sess.target_tlib_path.dir.clone() } else { - let default_sysroot = filesearch::get_or_default_sysroot(); - let default_tlib = - filesearch::make_target_lib_path(&default_sysroot, sess.opts.target_triple.tuple()); - default_tlib + filesearch::make_target_lib_path( + &sess.opts.sysroot.default, + sess.opts.target_triple.tuple(), + ) } } @@ -1758,7 +1758,7 @@ fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool { for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) { let full_path = dir.join(&linker_with_extension); // If linker comes from sysroot assume self-contained mode - if full_path.is_file() && !full_path.starts_with(&sess.sysroot) { + if full_path.is_file() && !full_path.starts_with(sess.opts.sysroot.path()) { return false; } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 8fc83908efbc..cd08c0fc30fb 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -337,7 +337,12 @@ pub(crate) trait Linker { fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]); fn no_crt_objects(&mut self); fn no_default_libraries(&mut self); - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]); + fn export_symbols( + &mut self, + tmpdir: &Path, + crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ); fn subsystem(&mut self, subsystem: &str); fn linker_plugin_lto(&mut self); fn add_eh_frame_header(&mut self) {} @@ -770,7 +775,12 @@ impl<'a> Linker for GccLinker<'a> { } } - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + tmpdir: &Path, + crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { // Symbol visibility in object files typically takes care of this. if crate_type == CrateType::Executable { let should_export_executable_symbols = @@ -799,7 +809,7 @@ impl<'a> Linker for GccLinker<'a> { // Write a plain, newline-separated list of symbols let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; - for sym in symbols { + for (sym, _) in symbols { debug!(" _{sym}"); writeln!(f, "_{sym}")?; } @@ -814,11 +824,12 @@ impl<'a> Linker for GccLinker<'a> { // .def file similar to MSVC one but without LIBRARY section // because LD doesn't like when it's empty writeln!(f, "EXPORTS")?; - for symbol in symbols { + for (symbol, kind) in symbols { + let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" }; debug!(" _{symbol}"); // Quote the name in case it's reserved by linker in some way // (this accounts for names with dots in particular). - writeln!(f, " \"{symbol}\"")?; + writeln!(f, " \"{symbol}\"{kind_marker}")?; } }; if let Err(error) = res { @@ -831,7 +842,7 @@ impl<'a> Linker for GccLinker<'a> { writeln!(f, "{{")?; if !symbols.is_empty() { writeln!(f, " global:")?; - for sym in symbols { + for (sym, _) in symbols { debug!(" {sym};"); writeln!(f, " {sym};")?; } @@ -1059,7 +1070,7 @@ impl<'a> Linker for MsvcLinker<'a> { self.link_arg("/PDBALTPATH:%_PDB%"); // This will cause the Microsoft linker to embed .natvis info into the PDB file - let natvis_dir_path = self.sess.sysroot.join("lib\\rustlib\\etc"); + let natvis_dir_path = self.sess.opts.sysroot.path().join("lib\\rustlib\\etc"); if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) { for entry in natvis_dir { match entry { @@ -1098,7 +1109,12 @@ impl<'a> Linker for MsvcLinker<'a> { // crates. Upstream rlibs may be linked statically to this dynamic library, // in which case they may continue to transitively be used and hence need // their symbols exported. - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + tmpdir: &Path, + crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { // Symbol visibility takes care of this typically if crate_type == CrateType::Executable { let should_export_executable_symbols = @@ -1116,9 +1132,10 @@ impl<'a> Linker for MsvcLinker<'a> { // straight to exports. writeln!(f, "LIBRARY")?; writeln!(f, "EXPORTS")?; - for symbol in symbols { + for (symbol, kind) in symbols { + let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" }; debug!(" _{symbol}"); - writeln!(f, " {symbol}")?; + writeln!(f, " {symbol}{kind_marker}")?; } }; if let Err(error) = res { @@ -1259,14 +1276,19 @@ impl<'a> Linker for EmLinker<'a> { self.cc_arg("-nodefaultlibs"); } - fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + _tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { debug!("EXPORTED SYMBOLS:"); self.cc_arg("-s"); let mut arg = OsString::from("EXPORTED_FUNCTIONS="); let encoded = serde_json::to_string( - &symbols.iter().map(|sym| "_".to_owned() + sym).collect::>(), + &symbols.iter().map(|(sym, _)| "_".to_owned() + sym).collect::>(), ) .unwrap(); debug!("{encoded}"); @@ -1428,8 +1450,13 @@ impl<'a> Linker for WasmLd<'a> { fn no_default_libraries(&mut self) {} - fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { - for sym in symbols { + fn export_symbols( + &mut self, + _tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { + for (sym, _) in symbols { self.link_args(&["--export", sym]); } @@ -1563,7 +1590,7 @@ impl<'a> Linker for L4Bender<'a> { self.cc_arg("-nostdlib"); } - fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) { + fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[(String, SymbolExportKind)]) { // ToDo, not implemented, copy from GCC self.sess.dcx().emit_warn(errors::L4BenderExportingSymbolsUnimplemented); } @@ -1720,12 +1747,17 @@ impl<'a> Linker for AixLinker<'a> { fn no_default_libraries(&mut self) {} - fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { let path = tmpdir.join("list.exp"); let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; // FIXME: use llvm-nm to generate export list. - for symbol in symbols { + for (symbol, _) in symbols { debug!(" _{symbol}"); writeln!(f, " {symbol}")?; } @@ -1769,9 +1801,23 @@ fn for_each_exported_symbols_include_dep<'tcx>( } } -pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec { +pub(crate) fn exported_symbols( + tcx: TyCtxt<'_>, + crate_type: CrateType, +) -> Vec<(String, SymbolExportKind)> { if let Some(ref exports) = tcx.sess.target.override_export_symbols { - return exports.iter().map(ToString::to_string).collect(); + return exports + .iter() + .map(|name| { + ( + name.to_string(), + // FIXME use the correct export kind for this symbol. override_export_symbols + // can't directly specify the SymbolExportKind as it is defined in rustc_middle + // which rustc_target can't depend on. + SymbolExportKind::Text, + ) + }) + .collect(); } if let CrateType::ProcMacro = crate_type { @@ -1781,7 +1827,10 @@ pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec, crate_type: CrateType) -> Vec { +fn exported_symbols_for_non_proc_macro( + tcx: TyCtxt<'_>, + crate_type: CrateType, +) -> Vec<(String, SymbolExportKind)> { let mut symbols = Vec::new(); let export_threshold = symbol_export::crates_export_threshold(&[crate_type]); for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| { @@ -1789,8 +1838,9 @@ fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) - // from any cdylib. The latter doesn't work anyway as we use hidden visibility for // compiler-builtins. Most linkers silently ignore it, but ld64 gives a warning. if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) { - symbols.push(symbol_export::exporting_symbol_name_for_instance_in_crate( - tcx, symbol, cnum, + symbols.push(( + symbol_export::exporting_symbol_name_for_instance_in_crate(tcx, symbol, cnum), + info.kind, )); symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, cnum); } @@ -1799,7 +1849,7 @@ fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) - symbols } -fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec { +fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<(String, SymbolExportKind)> { // `exported_symbols` will be empty when !should_codegen. if !tcx.sess.opts.output_types.should_codegen() { return Vec::new(); @@ -1809,7 +1859,10 @@ fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec { let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id); let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx); - vec![proc_macro_decls_name, metadata_symbol_name] + vec![ + (proc_macro_decls_name, SymbolExportKind::Data), + (metadata_symbol_name, SymbolExportKind::Data), + ] } pub(crate) fn linked_symbols( @@ -1831,7 +1884,9 @@ pub(crate) fn linked_symbols( || info.used { symbols.push(( - symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum), + symbol_export::linking_symbol_name_for_instance_in_crate( + tcx, symbol, info.kind, cnum, + ), info.kind, )); } @@ -1906,7 +1961,13 @@ impl<'a> Linker for PtxLinker<'a> { fn ehcont_guard(&mut self) {} - fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, _symbols: &[String]) {} + fn export_symbols( + &mut self, + _tmpdir: &Path, + _crate_type: CrateType, + _symbols: &[(String, SymbolExportKind)], + ) { + } fn subsystem(&mut self, _subsystem: &str) {} @@ -1975,10 +2036,15 @@ impl<'a> Linker for LlbcLinker<'a> { fn ehcont_guard(&mut self) {} - fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + _tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { match _crate_type { CrateType::Cdylib => { - for sym in symbols { + for (sym, _) in symbols { self.link_args(&["--export-symbol", sym]); } } @@ -2052,11 +2118,16 @@ impl<'a> Linker for BpfLinker<'a> { fn ehcont_guard(&mut self) {} - fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + fn export_symbols( + &mut self, + tmpdir: &Path, + _crate_type: CrateType, + symbols: &[(String, SymbolExportKind)], + ) { let path = tmpdir.join("symbols"); let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; - for sym in symbols { + for (sym, _) in symbols { writeln!(f, "{sym}")?; } }; diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index d0b6c7470fb9..19c005d418e8 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -680,6 +680,7 @@ fn calling_convention_for_symbol<'tcx>( pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>( tcx: TyCtxt<'tcx>, symbol: ExportedSymbol<'tcx>, + export_kind: SymbolExportKind, instantiating_crate: CrateNum, ) -> String { let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate); @@ -700,8 +701,9 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>( let prefix = match &target.arch[..] { "x86" => Some('_'), "x86_64" => None, - "arm64ec" => Some('#'), - // Only x86/64 use symbol decorations. + // Only functions are decorated for arm64ec. + "arm64ec" if export_kind == SymbolExportKind::Text => Some('#'), + // Only x86/64 and arm64ec use symbol decorations. _ => return undecorated, }; @@ -741,7 +743,7 @@ pub(crate) fn exporting_symbol_name_for_instance_in_crate<'tcx>( /// Add it to the symbols list for all kernel functions, so that it is exported in the linked /// object. pub(crate) fn extend_exported_symbols<'tcx>( - symbols: &mut Vec, + symbols: &mut Vec<(String, SymbolExportKind)>, tcx: TyCtxt<'tcx>, symbol: ExportedSymbol<'tcx>, instantiating_crate: CrateNum, @@ -755,7 +757,9 @@ pub(crate) fn extend_exported_symbols<'tcx>( let undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate); // Add the symbol for the kernel descriptor (with .kd suffix) - symbols.push(format!("{undecorated}.kd")); + // Per https://llvm.org/docs/AMDGPUUsage.html#symbols these will always be `STT_OBJECT` so + // export as data. + symbols.push((format!("{undecorated}.kd"), SymbolExportKind::Data)); } fn maybe_emutls_symbol_name<'tcx>( diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index bbf9cceef2a0..c3bfe4c13cdf 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -14,10 +14,10 @@ use rustc_data_structures::jobserver::{self, Acquired}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_errors::emitter::Emitter; -use rustc_errors::translation::Translate; +use rustc_errors::translation::Translator; use rustc_errors::{ - Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalError, FluentBundle, Level, MultiSpan, - Style, Suggestions, + Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalError, Level, MultiSpan, Style, + Suggestions, }; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -1889,16 +1889,6 @@ impl SharedEmitter { } } -impl Translate for SharedEmitter { - fn fluent_bundle(&self) -> Option<&FluentBundle> { - None - } - - fn fallback_fluent_bundle(&self) -> &FluentBundle { - panic!("shared emitter attempted to translate a diagnostic"); - } -} - impl Emitter for SharedEmitter { fn emit_diagnostic( &mut self, @@ -1932,6 +1922,10 @@ impl Emitter for SharedEmitter { fn source_map(&self) -> Option<&SourceMap> { None } + + fn translator(&self) -> &Translator { + panic!("shared emitter attempted to translate a diagnostic"); + } } impl SharedEmitterMain { diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index a3d6c73ba856..cc90271cd0c6 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -12,9 +12,9 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; use rustc_data_structures::sync::{IntoDynSyncSend, par_map}; use rustc_data_structures::unord::UnordMap; -use rustc_hir::ItemId; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; +use rustc_hir::{ItemId, Target}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType}; use rustc_middle::middle::exported_symbols::{self, SymbolExportKind}; @@ -1003,21 +1003,35 @@ impl CrateInfo { // by the compiler, but that's ok because all this stuff is unstable anyway. let target = &tcx.sess.target; if !are_upstream_rust_objects_already_included(tcx.sess) { - let missing_weak_lang_items: FxIndexSet = info + let add_prefix = match (target.is_like_windows, target.arch.as_ref()) { + (true, "x86") => |name: String, _: SymbolExportKind| format!("_{name}"), + (true, "arm64ec") => { + // Only functions are decorated for arm64ec. + |name: String, export_kind: SymbolExportKind| match export_kind { + SymbolExportKind::Text => format!("#{name}"), + _ => name, + } + } + _ => |name: String, _: SymbolExportKind| name, + }; + let missing_weak_lang_items: FxIndexSet<(Symbol, SymbolExportKind)> = info .used_crates .iter() .flat_map(|&cnum| tcx.missing_lang_items(cnum)) .filter(|l| l.is_weak()) .filter_map(|&l| { let name = l.link_name()?; - lang_items::required(tcx, l).then_some(name) + let export_kind = match l.target() { + Target::Fn => SymbolExportKind::Text, + Target::Static => SymbolExportKind::Data, + _ => bug!( + "Don't know what the export kind is for lang item of kind {:?}", + l.target() + ), + }; + lang_items::required(tcx, l).then_some((name, export_kind)) }) .collect(); - let prefix = match (target.is_like_windows, target.arch.as_ref()) { - (true, "x86") => "_", - (true, "arm64ec") => "#", - _ => "", - }; // This loop only adds new items to values of the hash map, so the order in which we // iterate over the values is not important. @@ -1030,10 +1044,13 @@ impl CrateInfo { .for_each(|(_, linked_symbols)| { let mut symbols = missing_weak_lang_items .iter() - .map(|item| { + .map(|(item, export_kind)| { ( - format!("{prefix}{}", mangle_internal_symbol(tcx, item.as_str())), - SymbolExportKind::Text, + add_prefix( + mangle_internal_symbol(tcx, item.as_str()), + *export_kind, + ), + *export_kind, ) }) .collect::>(); @@ -1048,12 +1065,12 @@ impl CrateInfo { // errors. linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| { ( - format!( - "{prefix}{}", + add_prefix( mangle_internal_symbol( tcx, - global_fn_name(method.name).as_str() - ) + global_fn_name(method.name).as_str(), + ), + SymbolExportKind::Text, ), SymbolExportKind::Text, ) diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 188a9a98ce7a..7bd27eb3ef1c 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -3,11 +3,9 @@ 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, + AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr, ReprAttr, find_attr, }; -use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; @@ -19,13 +17,16 @@ use rustc_middle::mir::mono::Linkage; use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::{self as ty, TyCtxt}; +use rustc_session::lint; use rustc_session::parse::feature_err; -use rustc_session::{Session, lint}; use rustc_span::{Ident, Span, sym}; use rustc_target::spec::SanitizerSet; use crate::errors; -use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature_attr}; +use crate::errors::NoMangleNameless; +use crate::target_features::{ + check_target_feature_trait_unsafe, check_tied_features, from_target_feature_attr, +}; fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage { use rustc_middle::mir::mono::Linkage::*; @@ -87,7 +88,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { let mut link_ordinal_span = None; let mut no_sanitize_span = None; let mut mixed_export_name_no_mangle_lint_state = MixedExportNameAndNoMangleState::default(); - let mut no_mangle_span = None; for attr in attrs.iter() { // In some cases, attribute are only valid on functions, but it's the `check_attr` @@ -95,17 +95,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // In these cases, we bail from performing further checks that are only meaningful for // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also // report a delayed bug, just in case `check_attr` isn't doing its job. - let fn_sig = || { + let fn_sig = |attr_span| { use DefKind::*; let def_kind = tcx.def_kind(did); if let Fn | AssocFn | Variant | Ctor(..) = def_kind { Some(tcx.fn_sig(did)) } else { - tcx.dcx().span_delayed_bug( - attr.span(), - "this attribute can only be applied to functions", - ); + tcx.dcx() + .span_delayed_bug(attr_span, "this attribute can only be applied to functions"); None } }; @@ -115,10 +113,56 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { AttributeKind::Repr(reprs) => { codegen_fn_attrs.alignment = reprs .iter() - .filter_map(|(r, _)| if let ReprAlign(x) = r { Some(*x) } else { None }) + .filter_map( + |(r, _)| if let ReprAttr::ReprAlign(x) = r { Some(*x) } else { None }, + ) .max(); } + AttributeKind::Cold(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD, + AttributeKind::Naked(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED, + AttributeKind::Align { align, .. } => codegen_fn_attrs.alignment = Some(*align), + AttributeKind::NoMangle(attr_span) => { + if tcx.opt_item_name(did.to_def_id()).is_some() { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; + mixed_export_name_no_mangle_lint_state.track_no_mangle( + *attr_span, + tcx.local_def_id_to_hir_id(did), + attr, + ); + } else { + tcx.dcx().emit_err(NoMangleNameless { + span: *attr_span, + definition: format!( + "{} {}", + tcx.def_descr_article(did.to_def_id()), + tcx.def_descr(did.to_def_id()) + ), + }); + } + } + AttributeKind::TrackCaller(attr_span) => { + let is_closure = tcx.is_closure_like(did.to_def_id()); + if !is_closure + && let Some(fn_sig) = fn_sig(*attr_span) + && fn_sig.skip_binder().abi() != ExternAbi::Rust + { + tcx.dcx().emit_err(errors::RequiresRustAbi { span: *attr_span }); + } + if is_closure + && !tcx.features().closure_track_caller() + && !attr_span.allows_unstable(sym::closure_track_caller) + { + feature_err( + &tcx.sess, + sym::closure_track_caller, + *attr_span, + "`#[track_caller]` on closures is currently unstable", + ) + .emit(); + } + codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER + } _ => {} } } @@ -128,7 +172,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { }; match name { - sym::cold => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD, sym::rustc_allocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR, sym::ffi_pure => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE, sym::ffi_const => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST, @@ -138,29 +181,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { sym::rustc_allocator_zeroed => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED } - sym::naked => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED, - sym::no_mangle => { - no_mangle_span = Some(attr.span()); - if tcx.opt_item_name(did.to_def_id()).is_some() { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; - mixed_export_name_no_mangle_lint_state.track_no_mangle( - attr.span(), - tcx.local_def_id_to_hir_id(did), - attr, - ); - } else { - tcx.dcx() - .struct_span_err( - attr.span(), - format!( - "`#[no_mangle]` cannot be used on {} {} as it has no name", - tcx.def_descr_article(did.to_def_id()), - tcx.def_descr(did.to_def_id()), - ), - ) - .emit(); - } - } sym::rustc_std_internal_symbol => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL } @@ -203,29 +223,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, - sym::track_caller => { - let is_closure = tcx.is_closure_like(did.to_def_id()); - - if !is_closure - && let Some(fn_sig) = fn_sig() - && fn_sig.skip_binder().abi() != ExternAbi::Rust - { - tcx.dcx().emit_err(errors::RequiresRustAbi { span: attr.span() }); - } - if is_closure - && !tcx.features().closure_track_caller() - && !attr.span().allows_unstable(sym::closure_track_caller) - { - feature_err( - &tcx.sess, - sym::closure_track_caller, - attr.span(), - "`#[track_caller]` on closures is currently unstable", - ) - .emit(); - } - codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER - } sym::export_name => { if let Some(s) = attr.value_str() { if s.as_str().contains('\0') { @@ -449,6 +446,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { mixed_export_name_no_mangle_lint_state.lint_if_mixed(tcx); + // Apply the minimum function alignment here, so that individual backends don't have to. + codegen_fn_attrs.alignment = + Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment); + let inline_span; (codegen_fn_attrs.inline, inline_span) = if let Some((inline_attr, span)) = find_attr!(attrs, AttributeKind::Inline(i, span) => (*i, *span)) @@ -465,33 +466,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs.inline = InlineAttr::Never; } - codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::Default, |ia, attr| { - if !attr.has_name(sym::optimize) { - return ia; - } - if attr.is_word() { - tcx.dcx().emit_err(errors::ExpectedOneArgumentOptimize { span: attr.span() }); - return ia; - } - let Some(ref items) = attr.meta_item_list() else { - return OptimizeAttr::Default; - }; - - let [item] = &items[..] else { - tcx.dcx().emit_err(errors::ExpectedOneArgumentOptimize { span: attr.span() }); - return OptimizeAttr::Default; - }; - if item.has_name(sym::size) { - OptimizeAttr::Size - } else if item.has_name(sym::speed) { - OptimizeAttr::Speed - } else if item.has_name(sym::none) { - OptimizeAttr::DoNotOptimize - } else { - tcx.dcx().emit_err(errors::InvalidArgumentOptimize { span: item.span() }); - OptimizeAttr::Default - } - }); + codegen_fn_attrs.optimize = + find_attr!(attrs, AttributeKind::Optimize(i, _) => *i).unwrap_or(OptimizeAttr::Default); // #73631: closures inherit `#[target_feature]` annotations // @@ -567,12 +543,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) && codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) { + let no_mangle_span = + find_attr!(attrs, AttributeKind::NoMangle(no_mangle_span) => *no_mangle_span) + .unwrap_or_default(); let lang_item = lang_items::extract(attrs).map_or(None, |(name, _span)| LangItem::from_name(name)); let mut err = tcx .dcx() .struct_span_err( - no_mangle_span.unwrap_or_default(), + no_mangle_span, "`#[no_mangle]` cannot be used on internal language items", ) .with_note("Rustc requires this item to have a specific mangled name.") @@ -625,25 +604,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs } -/// Given a map from target_features to whether they are enabled or disabled, ensure only valid -/// combinations are allowed. -pub fn check_tied_features( - sess: &Session, - features: &FxHashMap<&str, bool>, -) -> Option<&'static [&'static str]> { - if !features.is_empty() { - for tied in sess.target.tied_target_features() { - // Tied features must be set to the same value, or not set at all - let mut tied_iter = tied.iter(); - let enabled = features.get(tied_iter.next().unwrap()); - if tied_iter.any(|f| enabled != features.get(f)) { - return Some(tied); - } - } - } - None -} - /// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller /// applied to the method prototype. fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool { diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 5387b2a7f818..caac0f83f9d9 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -208,20 +208,6 @@ pub(crate) struct OutOfRangeInteger { pub span: Span, } -#[derive(Diagnostic)] -#[diag(codegen_ssa_expected_one_argument, code = E0722)] -pub(crate) struct ExpectedOneArgumentOptimize { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(codegen_ssa_invalid_argument, code = E0722)] -pub(crate) struct InvalidArgumentOptimize { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(codegen_ssa_copy_path_buf)] pub(crate) struct CopyPathBuf { @@ -1217,30 +1203,6 @@ pub(crate) struct ErrorCreatingImportLibrary<'a> { pub error: String, } -pub struct TargetFeatureDisableOrEnable<'a> { - pub features: &'a [&'a str], - pub span: Option, - pub missing_features: Option, -} - -#[derive(Subdiagnostic)] -#[help(codegen_ssa_missing_features)] -pub struct MissingFeatures; - -impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::codegen_ssa_target_feature_disable_or_enable); - if let Some(span) = self.span { - diag.span(span); - }; - if let Some(missing_features) = self.missing_features { - diag.subdiagnostic(missing_features); - } - diag.arg("features", self.features.join(", ")); - diag - } -} - #[derive(Diagnostic)] #[diag(codegen_ssa_aix_strip_not_used)] pub(crate) struct AixStripNotUsed; @@ -1283,3 +1245,76 @@ pub(crate) struct XcrunSdkPathWarning { #[derive(LintDiagnostic)] #[diag(codegen_ssa_aarch64_softfloat_neon)] pub(crate) struct Aarch64SoftfloatNeon; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unknown_ctarget_feature_prefix)] +#[note] +pub(crate) struct UnknownCTargetFeaturePrefix<'a> { + pub feature: &'a str, +} + +#[derive(Subdiagnostic)] +pub(crate) enum PossibleFeature<'a> { + #[help(codegen_ssa_possible_feature)] + Some { rust_feature: &'a str }, + #[help(codegen_ssa_consider_filing_feature_request)] + None, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unknown_ctarget_feature)] +#[note] +pub(crate) struct UnknownCTargetFeature<'a> { + pub feature: &'a str, + #[subdiagnostic] + pub rust_feature: PossibleFeature<'a>, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unstable_ctarget_feature)] +#[note] +pub(crate) struct UnstableCTargetFeature<'a> { + pub feature: &'a str, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_forbidden_ctarget_feature)] +#[note] +#[note(codegen_ssa_forbidden_ctarget_feature_issue)] +pub(crate) struct ForbiddenCTargetFeature<'a> { + pub feature: &'a str, + pub enabled: &'a str, + pub reason: &'a str, +} + +pub struct TargetFeatureDisableOrEnable<'a> { + pub features: &'a [&'a str], + pub span: Option, + pub missing_features: Option, +} + +#[derive(Subdiagnostic)] +#[help(codegen_ssa_missing_features)] +pub struct MissingFeatures; + +impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { + let mut diag = Diag::new(dcx, level, fluent::codegen_ssa_target_feature_disable_or_enable); + if let Some(span) = self.span { + diag.span(span); + }; + if let Some(missing_features) = self.missing_features { + diag.subdiagnostic(missing_features); + } + diag.arg("features", self.features.join(", ")); + diag + } +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_no_mangle_nameless)] +pub(crate) struct NoMangleNameless { + #[primary_span] + pub span: Span, + pub definition: String, +} diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 523c9f2ad1ce..23ed387a3ff9 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -218,7 +218,7 @@ pub struct CrateInfo { pub target_cpu: String, pub target_features: Vec, pub crate_types: Vec, - pub exported_symbols: UnordMap>, + pub exported_symbols: UnordMap>, pub linked_symbols: FxIndexMap>, pub local_crate_name: Symbol, pub compiler_builtins: Option, diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 9f66457a7400..9da4b8cc8fd4 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -131,12 +131,8 @@ fn prefix_and_suffix<'tcx>( let attrs = tcx.codegen_fn_attrs(instance.def_id()); let link_section = attrs.link_section.map(|symbol| symbol.as_str().to_string()); - // function alignment can be set globally with the `-Zmin-function-alignment=` flag; - // the alignment from a `#[repr(align())]` is used if it specifies a higher alignment. - // if no alignment is specified, an alignment of 4 bytes is used. - let min_function_alignment = tcx.sess.opts.unstable_opts.min_function_alignment; - let align_bytes = - Ord::max(min_function_alignment, attrs.alignment).map(|a| a.bytes()).unwrap_or(4); + // If no alignment is specified, an alignment of 4 bytes is used. + let align_bytes = attrs.alignment.map(|a| a.bytes()).unwrap_or(4); // In particular, `.arm` can also be written `.code 32` and `.thumb` as `.code 16`. let (arch_prefix, arch_suffix) = if is_arm { diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index e1d8b7546cf4..db5ac6a514fb 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -1123,7 +1123,7 @@ pub(super) fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // While optimizations will remove no-op transmutes, they might still be // there in debug or things that aren't no-op in MIR because they change // the Rust type but not the underlying layout/niche. - if from_scalar == to_scalar && from_backend_ty == to_backend_ty { + if from_scalar == to_scalar { return imm; } @@ -1142,7 +1142,13 @@ pub(super) fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( assume_scalar_range(bx, imm, from_scalar, from_backend_ty); imm = match (from_scalar.primitive(), to_scalar.primitive()) { - (Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty), + (Int(..) | Float(_), Int(..) | Float(_)) => { + if from_backend_ty == to_backend_ty { + imm + } else { + bx.bitcast(imm, to_backend_ty) + } + } (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), (Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm), (Pointer(..), Int(..)) => { diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 640d197c219a..67ac619091be 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -1,5 +1,5 @@ use rustc_attr_data_structures::InstructionSetAttr; -use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::Applicability; use rustc_hir as hir; @@ -8,11 +8,12 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_middle::middle::codegen_fn_attrs::TargetFeature; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; -use rustc_session::features::StabilityExt; +use rustc_session::Session; use rustc_session::lint::builtin::AARCH64_SOFTFLOAT_NEON; use rustc_session::parse::feature_err; use rustc_span::{Span, Symbol, sym}; -use rustc_target::target_features::{self, Stability}; +use rustc_target::target_features::{self, RUSTC_SPECIFIC_FEATURES, Stability}; +use smallvec::SmallVec; use crate::errors; @@ -67,7 +68,7 @@ pub(crate) fn from_target_feature_attr( // Only allow target features whose feature gates have been enabled // and which are permitted to be toggled. - if let Err(reason) = stability.is_toggle_permitted(tcx.sess) { + if let Err(reason) = stability.toggle_allowed() { tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr { span: item.span(), feature, @@ -88,7 +89,7 @@ pub(crate) fn from_target_feature_attr( let feature_sym = Symbol::intern(feature); for &name in tcx.implied_target_features(feature_sym) { // But ensure the ABI does not forbid enabling this. - // Here we do assume that LLVM doesn't add even more implied features + // Here we do assume that the backend doesn't add even more implied features // we don't know about, at least no features that would have ABI effects! // We skip this logic in rustdoc, where we want to allow all target features of // all targets, so we can't check their ABI compatibility and anyway we are not @@ -156,6 +157,276 @@ pub(crate) fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, } } +/// Parse the value of `-Ctarget-feature`, also expanding implied features, +/// and call the closure for each (expanded) Rust feature. If the list contains +/// a syntactically invalid item (not starting with `+`/`-`), the error callback is invoked. +fn parse_rust_feature_flag<'a>( + sess: &'a Session, + err_callback: impl Fn(&'a str), + mut callback: impl FnMut( + /* base_feature */ &'a str, + /* with_implied */ FxHashSet<&'a str>, + /* enable */ bool, + ), +) { + // A cache for the backwards implication map. + let mut inverse_implied_features: Option>> = None; + + for feature in sess.opts.cg.target_feature.split(',') { + if let Some(base_feature) = feature.strip_prefix('+') { + // Skip features that are not target features, but rustc features. + if RUSTC_SPECIFIC_FEATURES.contains(&base_feature) { + return; + } + + callback(base_feature, sess.target.implied_target_features(base_feature), true) + } else if let Some(base_feature) = feature.strip_prefix('-') { + // Skip features that are not target features, but rustc features. + if RUSTC_SPECIFIC_FEATURES.contains(&base_feature) { + return; + } + + // If `f1` implies `f2`, then `!f2` implies `!f1` -- this is standard logical + // contraposition. So we have to find all the reverse implications of `base_feature` and + // disable them, too. + + let inverse_implied_features = inverse_implied_features.get_or_insert_with(|| { + let mut set: FxHashMap<&str, FxHashSet<&str>> = FxHashMap::default(); + for (f, _, is) in sess.target.rust_target_features() { + for i in is.iter() { + set.entry(i).or_default().insert(f); + } + } + set + }); + + // Inverse implied target features have their own inverse implied target features, so we + // traverse the map until there are no more features to add. + let mut features = FxHashSet::default(); + let mut new_features = vec![base_feature]; + while let Some(new_feature) = new_features.pop() { + if features.insert(new_feature) { + if let Some(implied_features) = inverse_implied_features.get(&new_feature) { + new_features.extend(implied_features) + } + } + } + + callback(base_feature, features, false) + } else if !feature.is_empty() { + err_callback(feature) + } + } +} + +/// Utility function for a codegen backend to compute `cfg(target_feature)`, or more specifically, +/// to populate `sess.unstable_target_features` and `sess.target_features` (these are the first and +/// 2nd component of the return value, respectively). +/// +/// `target_base_has_feature` should check whether the given feature (a Rust feature name!) is +/// enabled in the "base" target machine, i.e., without applying `-Ctarget-feature`. +/// +/// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled elsewhere. +pub fn cfg_target_feature( + sess: &Session, + mut target_base_has_feature: impl FnMut(&str) -> bool, +) -> (Vec, Vec) { + // Compute which of the known target features are enabled in the 'base' target machine. We only + // consider "supported" features; "forbidden" features are not reflected in `cfg` as of now. + let mut features: UnordSet = sess + .target + .rust_target_features() + .iter() + .filter(|(feature, _, _)| target_base_has_feature(feature)) + .map(|(feature, _, _)| Symbol::intern(feature)) + .collect(); + + // Add enabled and remove disabled features. + parse_rust_feature_flag( + sess, + /* err_callback */ + |_| { + // Errors are already emitted in `flag_to_backend_features`; avoid duplicates. + }, + |_base_feature, new_features, enabled| { + // Iteration order is irrelevant since this only influences an `UnordSet`. + #[allow(rustc::potential_query_instability)] + if enabled { + features.extend(new_features.into_iter().map(|f| Symbol::intern(f))); + } else { + // Remove `new_features` from `features`. + for new in new_features { + features.remove(&Symbol::intern(new)); + } + } + }, + ); + + // Filter enabled features based on feature gates. + let f = |allow_unstable| { + sess.target + .rust_target_features() + .iter() + .filter_map(|(feature, gate, _)| { + // The `allow_unstable` set is used by rustc internally to determine which target + // features are truly available, so we want to return even perma-unstable + // "forbidden" features. + if allow_unstable + || (gate.in_cfg() + && (sess.is_nightly_build() || gate.requires_nightly().is_none())) + { + Some(Symbol::intern(feature)) + } else { + None + } + }) + .filter(|feature| features.contains(&feature)) + .collect() + }; + + (f(true), f(false)) +} + +/// Given a map from target_features to whether they are enabled or disabled, ensure only valid +/// combinations are allowed. +pub fn check_tied_features( + sess: &Session, + features: &FxHashMap<&str, bool>, +) -> Option<&'static [&'static str]> { + if !features.is_empty() { + for tied in sess.target.tied_target_features() { + // Tied features must be set to the same value, or not set at all + let mut tied_iter = tied.iter(); + let enabled = features.get(tied_iter.next().unwrap()); + if tied_iter.any(|f| enabled != features.get(f)) { + return Some(tied); + } + } + } + None +} + +/// Translates the `-Ctarget-feature` flag into a backend target feature list. +/// +/// `to_backend_features` converts a Rust feature name into a list of backend feature names; this is +/// used for diagnostic purposes only. +/// +/// `extend_backend_features` extends the set of backend features (assumed to be in mutable state +/// accessible by that closure) to enable/disable the given Rust feature name. +pub fn flag_to_backend_features<'a, const N: usize>( + sess: &'a Session, + diagnostics: bool, + to_backend_features: impl Fn(&'a str) -> SmallVec<[&'a str; N]>, + mut extend_backend_features: impl FnMut(&'a str, /* enable */ bool), +) { + let known_features = sess.target.rust_target_features(); + + // Compute implied features + let mut rust_features = vec![]; + parse_rust_feature_flag( + sess, + /* err_callback */ + |feature| { + if diagnostics { + sess.dcx().emit_warn(errors::UnknownCTargetFeaturePrefix { feature }); + } + }, + |base_feature, new_features, enable| { + rust_features.extend( + UnordSet::from(new_features).to_sorted_stable_ord().iter().map(|&&s| (enable, s)), + ); + // Check feature validity. + if diagnostics { + let feature_state = known_features.iter().find(|&&(v, _, _)| v == base_feature); + match feature_state { + None => { + // This is definitely not a valid Rust feature name. Maybe it is a backend + // feature name? If so, give a better error message. + let rust_feature = + known_features.iter().find_map(|&(rust_feature, _, _)| { + let backend_features = to_backend_features(rust_feature); + if backend_features.contains(&base_feature) + && !backend_features.contains(&rust_feature) + { + Some(rust_feature) + } else { + None + } + }); + let unknown_feature = if let Some(rust_feature) = rust_feature { + errors::UnknownCTargetFeature { + feature: base_feature, + rust_feature: errors::PossibleFeature::Some { rust_feature }, + } + } else { + errors::UnknownCTargetFeature { + feature: base_feature, + rust_feature: errors::PossibleFeature::None, + } + }; + sess.dcx().emit_warn(unknown_feature); + } + Some((_, stability, _)) => { + if let Err(reason) = stability.toggle_allowed() { + sess.dcx().emit_warn(errors::ForbiddenCTargetFeature { + feature: base_feature, + enabled: if enable { "enabled" } else { "disabled" }, + reason, + }); + } else if stability.requires_nightly().is_some() { + // An unstable feature. Warn about using it. It makes little sense + // to hard-error here since we just warn about fully unknown + // features above. + sess.dcx().emit_warn(errors::UnstableCTargetFeature { + feature: base_feature, + }); + } + } + } + } + }, + ); + + if diagnostics { + // FIXME(nagisa): figure out how to not allocate a full hashmap here. + if let Some(f) = check_tied_features( + sess, + &FxHashMap::from_iter(rust_features.iter().map(|&(enable, feature)| (feature, enable))), + ) { + sess.dcx().emit_err(errors::TargetFeatureDisableOrEnable { + features: f, + span: None, + missing_features: None, + }); + } + } + + // Add this to the backend features. + for (enable, feature) in rust_features { + extend_backend_features(feature, enable); + } +} + +/// Computes the backend target features to be added to account for retpoline flags. +/// Used by both LLVM and GCC since their target features are, conveniently, the same. +pub fn retpoline_features_by_flags(sess: &Session, features: &mut Vec) { + // -Zretpoline without -Zretpoline-external-thunk enables + // retpoline-indirect-branches and retpoline-indirect-calls target features + let unstable_opts = &sess.opts.unstable_opts; + if unstable_opts.retpoline && !unstable_opts.retpoline_external_thunk { + features.push("+retpoline-indirect-branches".into()); + features.push("+retpoline-indirect-calls".into()); + } + // -Zretpoline-external-thunk (maybe, with -Zretpoline too) enables + // retpoline-external-thunk, retpoline-indirect-branches and + // retpoline-indirect-calls target features + if unstable_opts.retpoline_external_thunk { + features.push("+retpoline-external-thunk".into()); + features.push("+retpoline-indirect-branches".into()); + features.push("+retpoline-indirect-calls".into()); + } +} + pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { rust_target_features: |tcx, cnum| { @@ -182,7 +453,8 @@ pub(crate) fn provide(providers: &mut Providers) { Stability::Unstable { .. } | Stability::Forbidden { .. }, ) | (Stability::Forbidden { .. }, Stability::Forbidden { .. }) => { - // The stability in the entry is at least as good as the new one, just keep it. + // The stability in the entry is at least as good as the new + // one, just keep it. } _ => { // Overwrite stabilite. diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index f35f551d5906..d19de6f5d267 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -516,7 +516,7 @@ pub trait BuilderMethods<'a, 'tcx>: // These are used by everyone except msvc fn cleanup_landing_pad(&mut self, pers_fn: Self::Function) -> (Self::Value, Self::Value); - fn filter_landing_pad(&mut self, pers_fn: Self::Function) -> (Self::Value, Self::Value); + fn filter_landing_pad(&mut self, pers_fn: Self::Function); fn resume(&mut self, exn0: Self::Value, exn1: Self::Value); // These are used only by msvc diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 4f252f3ccd48..576b174369d4 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -463,12 +463,6 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { ); } - fn crate_inject_span(&self) -> Option { - self.tcx.hir_crate_items(()).definitions().next().and_then(|id| { - self.tcx.crate_level_attribute_injection_span(self.tcx.local_def_id_to_hir_id(id)) - }) - } - /// Check the const stability of the given item (fn or trait). fn check_callee_stability(&mut self, def_id: DefId) { match self.tcx.lookup_const_stability(def_id) { @@ -543,7 +537,6 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { feature, feature_enabled, safe_to_expose_on_stable: callee_safe_to_expose_on_stable, - suggestion_span: self.crate_inject_span(), is_function_call: self.tcx.def_kind(def_id) != DefKind::Trait, }); } @@ -919,7 +912,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { name: intrinsic.name, feature, const_stable_indirect: is_const_stable, - suggestion: self.crate_inject_span(), }); } Some(attrs::ConstStability { diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 9c30dbff99eb..f5b7a6066c8b 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -1,8 +1,8 @@ //! Concrete error types for all operations which may be invalid in a certain const context. use hir::{ConstContext, LangItem}; +use rustc_errors::Diag; use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diag}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; @@ -384,7 +384,6 @@ pub(crate) struct CallUnstable { /// expose on stable. pub feature_enabled: bool, pub safe_to_expose_on_stable: bool, - pub suggestion_span: Option, /// true if `def_id` is the function we are calling, false if `def_id` is an unstable trait. pub is_function_call: bool, } @@ -412,20 +411,7 @@ impl<'tcx> NonConstOp<'tcx> for CallUnstable { def_path: ccx.tcx.def_path_str(self.def_id), }) }; - // FIXME: make this translatable - let msg = format!("add `#![feature({})]` to the crate attributes to enable", self.feature); - #[allow(rustc::untranslatable_diagnostic)] - if let Some(span) = self.suggestion_span { - err.span_suggestion_verbose( - span, - msg, - format!("#![feature({})]\n", self.feature), - Applicability::MachineApplicable, - ); - } else { - err.help(msg); - } - + ccx.tcx.disabled_nightly_features(&mut err, [(String::new(), self.feature)]); err } } @@ -452,7 +438,6 @@ pub(crate) struct IntrinsicUnstable { pub name: Symbol, pub feature: Symbol, pub const_stable_indirect: bool, - pub suggestion: Option, } impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable { @@ -472,8 +457,7 @@ impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable { span, name: self.name, feature: self.feature, - suggestion: self.suggestion, - help: self.suggestion.is_none(), + suggestion: ccx.tcx.crate_level_attribute_injection_span(), }) } } @@ -616,11 +600,13 @@ impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow { kind: ccx.const_kind(), teach: ccx.tcx.sess.teach(E0764), }), - hir::BorrowKind::Ref => ccx.dcx().create_err(errors::MutableRefEscaping { - span, - kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(E0764), - }), + hir::BorrowKind::Ref | hir::BorrowKind::Pin => { + ccx.dcx().create_err(errors::MutableRefEscaping { + span, + kind: ccx.const_kind(), + teach: ccx.tcx.sess.teach(E0764), + }) + } } } } diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 037cbf777e70..609749554cec 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -136,9 +136,7 @@ pub(crate) struct UnstableIntrinsic { code = "#![feature({feature})]\n", applicability = "machine-applicable" )] - pub suggestion: Option, - #[help(const_eval_unstable_intrinsic_suggestion)] - pub help: bool, + pub suggestion: Span, } #[derive(Diagnostic)] @@ -293,6 +291,9 @@ impl Subdiagnostic for FrameNote { span.push_span_label(self.span, fluent::const_eval_frame_note_last); } let msg = diag.eagerly_translate(fluent::const_eval_frame_note); + diag.remove_arg("times"); + diag.remove_arg("where_"); + diag.remove_arg("instance"); diag.span_note(span, msg); } } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 99a4bc1b7d6e..57bf867e389b 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -877,12 +877,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if let Some(fn_val) = self.get_fn_alloc(id) { let align = match fn_val { FnVal::Instance(instance) => { - // Function alignment can be set globally with the `-Zmin-function-alignment=` flag; - // the alignment from a `#[repr(align())]` is used if it specifies a higher alignment. - let fn_align = self.tcx.codegen_fn_attrs(instance.def_id()).alignment; - let global_align = self.tcx.sess.opts.unstable_opts.min_function_alignment; - - Ord::max(global_align, fn_align).unwrap_or(Align::ONE) + self.tcx.codegen_fn_attrs(instance.def_id()).alignment.unwrap_or(Align::ONE) } // Machine-specific extra functions currently do not support alignment restrictions. FnVal::Other(_) => Align::ONE, @@ -1412,8 +1407,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let src_alloc = self.get_alloc_raw(src_alloc_id)?; let src_range = alloc_range(src_offset, size); assert!(!self.memory.validation_in_progress.get(), "we can't be copying during validation"); - // For the overlapping case, it is crucial that we trigger the read hook + + // Trigger read hooks. + // For the overlapping case, it is crucial that we trigger the read hooks // before the write hook -- the aliasing model cares about the order. + if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(src, size.bytes() as i64) { + M::before_alloc_read(self, alloc_id)?; + } M::before_memory_read( tcx, &self.machine, diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index f6a020116185..17204883fb03 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -14,7 +14,6 @@ indexmap = "2.4.0" jobserver_crate = { version = "0.1.28", package = "jobserver" } measureme = "12.0.1" rustc-hash = "2.0.0" -rustc-rayon-core = { version = "0.5.0" } rustc-stable-hash = { version = "0.1.0", features = ["nightly"] } rustc_arena = { path = "../rustc_arena" } rustc_graphviz = { path = "../rustc_graphviz" } @@ -22,6 +21,7 @@ rustc_hashes = { path = "../rustc_hashes" } rustc_index = { path = "../rustc_index", package = "rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } +rustc_thread_pool = { path = "../rustc_thread_pool" } smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] } stacker = "0.1.17" tempfile = "3.2" diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index b28c333d860c..3881f3c2aa84 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -22,8 +22,6 @@ //! | | | `parking_lot::Mutex` | //! | `RwLock` | `RefCell` | `parking_lot::RwLock` | //! | `MTLock` [^1] | `T` | `Lock` | -//! | | | | -//! | `ParallelIterator` | `Iterator` | `rayon::iter::ParallelIterator` | //! //! [^1]: `MTLock` is similar to `Lock`, but the serial version avoids the cost //! of a `RefCell`. This is appropriate when interior mutability is not diff --git a/compiler/rustc_data_structures/src/sync/lock.rs b/compiler/rustc_data_structures/src/sync/lock.rs index 2ccf06ccd4f0..a8161c515115 100644 --- a/compiler/rustc_data_structures/src/sync/lock.rs +++ b/compiler/rustc_data_structures/src/sync/lock.rs @@ -1,8 +1,6 @@ //! This module implements a lock which only uses synchronization if `might_be_dyn_thread_safe` is true. //! It implements `DynSend` and `DynSync` instead of the typical `Send` and `Sync` traits. -#![allow(dead_code)] - use std::fmt; #[derive(Clone, Copy, PartialEq)] diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs index ab65c7f3a6b5..b515c0bee8a6 100644 --- a/compiler/rustc_data_structures/src/sync/parallel.rs +++ b/compiler/rustc_data_structures/src/sync/parallel.rs @@ -1,8 +1,6 @@ //! This module defines parallel operations that are implemented in //! one way for the serial compiler, and another way the parallel compiler. -#![allow(dead_code)] - use std::any::Any; use std::panic::{AssertUnwindSafe, catch_unwind, resume_unwind}; @@ -96,7 +94,7 @@ macro_rules! parallel { pub fn spawn(func: impl FnOnce() + DynSend + 'static) { if mode::is_dyn_thread_safe() { let func = FromDyn::from(func); - rayon_core::spawn(|| { + rustc_thread_pool::spawn(|| { (func.into_inner())(); }); } else { @@ -107,11 +105,11 @@ pub fn spawn(func: impl FnOnce() + DynSend + 'static) { // This function only works when `mode::is_dyn_thread_safe()`. pub fn scope<'scope, OP, R>(op: OP) -> R where - OP: FnOnce(&rayon_core::Scope<'scope>) -> R + DynSend, + OP: FnOnce(&rustc_thread_pool::Scope<'scope>) -> R + DynSend, R: DynSend, { let op = FromDyn::from(op); - rayon_core::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner() + rustc_thread_pool::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner() } #[inline] @@ -124,7 +122,7 @@ where let oper_a = FromDyn::from(oper_a); let oper_b = FromDyn::from(oper_b); let (a, b) = parallel_guard(|guard| { - rayon_core::join( + rustc_thread_pool::join( move || guard.run(move || FromDyn::from(oper_a.into_inner()())), move || guard.run(move || FromDyn::from(oper_b.into_inner()())), ) @@ -158,7 +156,7 @@ fn par_slice( let (left, right) = items.split_at_mut(items.len() / 2); let mut left = state.for_each.derive(left); let mut right = state.for_each.derive(right); - rayon_core::join(move || par_rec(*left, state), move || par_rec(*right, state)); + rustc_thread_pool::join(move || par_rec(*left, state), move || par_rec(*right, state)); } } @@ -241,7 +239,7 @@ pub fn par_map, R: DynSend, C: FromIterato pub fn broadcast(op: impl Fn(usize) -> R + DynSync) -> Vec { if mode::is_dyn_thread_safe() { let op = FromDyn::from(op); - let results = rayon_core::broadcast(|context| op.derive(op(context.index()))); + let results = rustc_thread_pool::broadcast(|context| op.derive(op(context.index()))); results.into_iter().map(|r| r.into_inner()).collect() } else { vec![op(0)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index d53126d04143..4855fc58d034 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -38,6 +38,7 @@ use rustc_data_structures::profiling::{ }; use rustc_errors::emitter::stderr_destination; use rustc_errors::registry::Registry; +use rustc_errors::translation::Translator; use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, FatalError, PResult, markdown}; use rustc_feature::find_gated_cfg; // This avoids a false positive with `-Wunused_crate_dependencies`. @@ -52,13 +53,13 @@ use rustc_metadata::locator; use rustc_middle::ty::TyCtxt; use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_session::config::{ - CG_OPTIONS, CrateType, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, + CG_OPTIONS, CrateType, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, Sysroot, UnstableOptions, Z_OPTIONS, nightly_options, parse_target_triple, }; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; use rustc_session::output::{CRATE_TYPES, collect_crate_types, invalid_output_for_target}; -use rustc_session::{EarlyDiagCtxt, Session, config, filesearch}; +use rustc_session::{EarlyDiagCtxt, Session, config}; use rustc_span::FileName; use rustc_span::def_id::LOCAL_CRATE; use rustc_target::json::ToJson; @@ -109,6 +110,10 @@ use crate::session_diagnostics::{ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } +pub fn default_translator() -> Translator { + Translator::with_fallback_bundle(DEFAULT_LOCALE_RESOURCES.to_vec(), false) +} + pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ // tidy-alphabetical-start crate::DEFAULT_LOCALE_RESOURCE, @@ -657,7 +662,7 @@ fn print_crate_info( println_info!("{}", targets.join("\n")); } HostTuple => println_info!("{}", rustc_session::config::host_tuple()), - Sysroot => println_info!("{}", sess.sysroot.display()), + Sysroot => println_info!("{}", sess.opts.sysroot.path().display()), TargetLibdir => println_info!("{}", sess.target_tlib_path.dir.display()), TargetSpecJson => { println_info!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap()); @@ -1109,8 +1114,8 @@ fn get_backend_from_raw_matches( let debug_flags = matches.opt_strs("Z"); let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); let target = parse_target_triple(early_dcx, matches); - let sysroot = filesearch::materialize_sysroot(matches.opt_str("sysroot").map(PathBuf::from)); - let target = config::build_target_config(early_dcx, &target, &sysroot); + let sysroot = Sysroot::new(matches.opt_str("sysroot").map(PathBuf::from)); + let target = config::build_target_config(early_dcx, &target, sysroot.path()); get_codegen_backend(early_dcx, &sysroot, backend_name, &target) } @@ -1413,11 +1418,10 @@ fn report_ice( extra_info: fn(&DiagCtxt), using_internal_features: &AtomicBool, ) { - let fallback_bundle = - rustc_errors::fallback_fluent_bundle(crate::DEFAULT_LOCALE_RESOURCES.to_vec(), false); + let translator = default_translator(); let emitter = Box::new(rustc_errors::emitter::HumanEmitter::new( stderr_destination(rustc_errors::ColorConfig::Auto), - fallback_bundle, + translator, )); let dcx = rustc_errors::DiagCtxt::new(emitter); let dcx = dcx.handle(); diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index ec77043cd128..688307a941f3 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -292,7 +292,11 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { } HirTree => { debug!("pretty printing HIR tree"); - format!("{:#?}", ex.tcx().hir_crate(())) + ex.tcx() + .hir_crate_items(()) + .owners() + .map(|owner| format!("{:#?} => {:#?}\n", owner, ex.tcx().hir_owner_nodes(owner))) + .collect() } Mir => { let mut out = Vec::new(); diff --git a/compiler/rustc_error_codes/src/error_codes/E0722.md b/compiler/rustc_error_codes/src/error_codes/E0722.md index 570717a92bd7..1799458d46cb 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0722.md +++ b/compiler/rustc_error_codes/src/error_codes/E0722.md @@ -1,8 +1,14 @@ +#### Note: this error code is no longer emitted by the compiler + +This is because it was too specific to the `optimize` attribute. +Similar diagnostics occur for other attributes too. +The example here will now emit `E0539` + The `optimize` attribute was malformed. Erroneous code example: -```compile_fail,E0722 +```compile_fail,E0539 #![feature(optimize_attribute)] #[optimize(something)] // error: invalid argument diff --git a/compiler/rustc_error_codes/src/error_codes/E0775.md b/compiler/rustc_error_codes/src/error_codes/E0775.md index efbd51e89ea3..9fcd3a6eef74 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0775.md +++ b/compiler/rustc_error_codes/src/error_codes/E0775.md @@ -8,7 +8,7 @@ Erroneous code example: ```ignore (no longer emitted) #![feature(cmse_nonsecure_entry)] -pub extern "C-cmse-nonsecure-entry" fn entry_function() {} +pub extern "cmse-nonsecure-entry" fn entry_function() {} ``` To fix this error, compile your code for a Rust target that supports the diff --git a/compiler/rustc_error_codes/src/error_codes/E0781.md b/compiler/rustc_error_codes/src/error_codes/E0781.md index 7641acfb5249..22abe0e3cb15 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0781.md +++ b/compiler/rustc_error_codes/src/error_codes/E0781.md @@ -1,12 +1,12 @@ -The `C-cmse-nonsecure-call` ABI can only be used with function pointers. +The `cmse-nonsecure-call` ABI can only be used with function pointers. Erroneous code example: ```compile_fail,E0781 -#![feature(abi_c_cmse_nonsecure_call)] +#![feature(abi_cmse_nonsecure_call)] -pub extern "C-cmse-nonsecure-call" fn test() {} +pub extern "cmse-nonsecure-call" fn test() {} ``` -The `C-cmse-nonsecure-call` ABI should be used by casting function pointers to +The `cmse-nonsecure-call` ABI should be used by casting function pointers to specific addresses. diff --git a/compiler/rustc_error_codes/src/error_codes/E0798.md b/compiler/rustc_error_codes/src/error_codes/E0798.md index da08cde30100..e5f356ef4d50 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0798.md +++ b/compiler/rustc_error_codes/src/error_codes/E0798.md @@ -1,4 +1,4 @@ -Functions marked as `C-cmse-nonsecure-call` place restrictions on their +Functions marked as `cmse-nonsecure-call` place restrictions on their inputs and outputs. - inputs must fit in the 4 available 32-bit argument registers. Alignment @@ -12,12 +12,12 @@ see [arm's aapcs32](https://github.com/ARM-software/abi-aa/releases). Erroneous code example: -```ignore (only fails on supported targets) -#![feature(abi_c_cmse_nonsecure_call)] +```ignore (host errors will not match for target) +#![feature(abi_cmse_nonsecure_call)] #[no_mangle] pub fn test( - f: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32, + f: extern "cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32, ) -> u32 { f(1, 2, 3, 4, 5) } @@ -27,12 +27,12 @@ Arguments' alignment is respected. In the example below, padding is inserted so that the `u64` argument is passed in registers r2 and r3. There is then no room left for the final `f32` argument -```ignore (only fails on supported targets) -#![feature(abi_c_cmse_nonsecure_call)] +```ignore (host errors will not match for target) +#![feature(abi_cmse_nonsecure_call)] #[no_mangle] pub fn test( - f: extern "C-cmse-nonsecure-call" fn(u32, u64, f32) -> u32, + f: extern "cmse-nonsecure-call" fn(u32, u64, f32) -> u32, ) -> u32 { f(1, 2, 3.0) } diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 6f5e4829802e..0aff1c06e0a8 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -686,8 +686,9 @@ E0805: 0805, // E0707, // multiple elided lifetimes used in arguments of `async fn` // E0709, // multiple different lifetimes used in arguments of `async fn` // E0721, // `await` keyword +// E0722, // replaced with a generic attribute input check // E0723, // unstable feature in `const` context // E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`. // E0744, // merged into E0728 -// E0776, // Removed; cmse_nonsecure_entry is now `C-cmse-nonsecure-entry` +// E0776, // Removed; `#[cmse_nonsecure_entry]` is now `extern "cmse-nonsecure-entry"` // E0796, // unused error code. We use `static_mut_refs` lint instead. diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml index 5dc582b9c3a5..0951859fa531 100644 --- a/compiler/rustc_error_messages/Cargo.toml +++ b/compiler/rustc_error_messages/Cargo.toml @@ -16,7 +16,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } -smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" unic-langid = { version = "0.9.0", features = ["macros"] } # tidy-alphabetical-end diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 1d3b5b20751a..4e4345cfe0fd 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -8,7 +8,7 @@ use std::borrow::Cow; use std::error::Error; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::sync::{Arc, LazyLock}; use std::{fmt, fs, io}; @@ -18,10 +18,9 @@ pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue}; use fluent_syntax::parser::ParserError; use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker}; use intl_memoizer::concurrent::IntlLangMemoizer; -use rustc_data_structures::sync::IntoDynSyncSend; +use rustc_data_structures::sync::{DynSend, IntoDynSyncSend}; use rustc_macros::{Decodable, Encodable}; use rustc_span::Span; -use smallvec::SmallVec; use tracing::{instrument, trace}; pub use unic_langid::{LanguageIdentifier, langid}; @@ -107,7 +106,7 @@ impl From> for TranslationBundleError { /// (overriding any conflicting messages). #[instrument(level = "trace")] pub fn fluent_bundle( - sysroot_candidates: SmallVec<[PathBuf; 2]>, + sysroot_candidates: &[&Path], requested_locale: Option, additional_ftl_path: Option<&Path>, with_directionality_markers: bool, @@ -141,7 +140,8 @@ pub fn fluent_bundle( // If the user requests the default locale then don't try to load anything. if let Some(requested_locale) = requested_locale { let mut found_resources = false; - for mut sysroot in sysroot_candidates { + for sysroot in sysroot_candidates { + let mut sysroot = sysroot.to_path_buf(); sysroot.push("share"); sysroot.push("locale"); sysroot.push(requested_locale.to_string()); @@ -204,16 +204,16 @@ fn register_functions(bundle: &mut FluentBundle) { /// Type alias for the result of `fallback_fluent_bundle` - a reference-counted pointer to a lazily /// evaluated fluent bundle. -pub type LazyFallbackBundle = Arc FluentBundle>>; +pub type LazyFallbackBundle = + Arc FluentBundle + DynSend>>>; /// Return the default `FluentBundle` with standard "en-US" diagnostic messages. #[instrument(level = "trace", skip(resources))] -#[define_opaque(LazyFallbackBundle)] pub fn fallback_fluent_bundle( resources: Vec<&'static str>, with_directionality_markers: bool, ) -> LazyFallbackBundle { - Arc::new(LazyLock::new(move || { + Arc::new(LazyLock::new(Box::new(move || { let mut fallback_bundle = new_bundle(vec![langid!("en-US")]); register_functions(&mut fallback_bundle); @@ -228,7 +228,7 @@ pub fn fallback_fluent_bundle( } fallback_bundle - })) + }))) } /// Identifier for the Fluent message/attribute corresponding to a diagnostic message. diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index f3aeb8d224b9..2eb3c23259ff 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -15,17 +15,15 @@ use rustc_span::source_map::SourceMap; use crate::emitter::FileWithAnnotatedLines; use crate::registry::Registry; use crate::snippet::Line; -use crate::translation::{Translate, to_fluent_args}; +use crate::translation::{Translator, to_fluent_args}; use crate::{ - CodeSuggestion, DiagInner, DiagMessage, Emitter, ErrCode, FluentBundle, LazyFallbackBundle, - Level, MultiSpan, Style, Subdiag, + CodeSuggestion, DiagInner, DiagMessage, Emitter, ErrCode, Level, MultiSpan, Style, Subdiag, }; /// Generates diagnostics using annotate-snippet pub struct AnnotateSnippetEmitter { source_map: Option>, - fluent_bundle: Option>, - fallback_bundle: LazyFallbackBundle, + translator: Translator, /// If true, hides the longer explanation text short_message: bool, @@ -35,16 +33,6 @@ pub struct AnnotateSnippetEmitter { macro_backtrace: bool, } -impl Translate for AnnotateSnippetEmitter { - fn fluent_bundle(&self) -> Option<&FluentBundle> { - self.fluent_bundle.as_deref() - } - - fn fallback_fluent_bundle(&self) -> &FluentBundle { - &self.fallback_bundle - } -} - impl Emitter for AnnotateSnippetEmitter { /// The entry point for the diagnostics generation fn emit_diagnostic(&mut self, mut diag: DiagInner, _registry: &Registry) { @@ -78,6 +66,10 @@ impl Emitter for AnnotateSnippetEmitter { fn should_show_explain(&self) -> bool { !self.short_message } + + fn translator(&self) -> &Translator { + &self.translator + } } /// Provides the source string for the given `line` of `file` @@ -104,19 +96,11 @@ fn annotation_level_for_level(level: Level) -> annotate_snippets::Level { impl AnnotateSnippetEmitter { pub fn new( source_map: Option>, - fluent_bundle: Option>, - fallback_bundle: LazyFallbackBundle, + translator: Translator, short_message: bool, macro_backtrace: bool, ) -> Self { - Self { - source_map, - fluent_bundle, - fallback_bundle, - short_message, - ui_testing: false, - macro_backtrace, - } + Self { source_map, translator, short_message, ui_testing: false, macro_backtrace } } /// Allows to modify `Self` to enable or disable the `ui_testing` flag. @@ -137,7 +121,7 @@ impl AnnotateSnippetEmitter { _children: &[Subdiag], _suggestions: &[CodeSuggestion], ) { - let message = self.translate_messages(messages, args); + let message = self.translator.translate_messages(messages, args); if let Some(source_map) = &self.source_map { // Make sure our primary file comes first let primary_lo = if let Some(primary_span) = msp.primary_span().as_ref() { diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a11f81b55bb8..8da7cdd93588 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -289,6 +289,9 @@ pub struct DiagInner { pub suggestions: Suggestions, pub args: DiagArgMap, + // This is used to store args and restore them after a subdiagnostic is rendered. + pub reserved_args: DiagArgMap, + /// This is not used for highlighting or rendering any error message. Rather, it can be used /// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of /// `span` if there is one. Otherwise, it is `DUMMY_SP`. @@ -319,6 +322,7 @@ impl DiagInner { children: vec![], suggestions: Suggestions::Enabled(vec![]), args: Default::default(), + reserved_args: Default::default(), sort_span: DUMMY_SP, is_lint: None, long_ty_path: None, @@ -390,7 +394,27 @@ impl DiagInner { } pub(crate) fn arg(&mut self, name: impl Into, arg: impl IntoDiagArg) { - self.args.insert(name.into(), arg.into_diag_arg(&mut self.long_ty_path)); + let name = name.into(); + let value = arg.into_diag_arg(&mut self.long_ty_path); + // This assertion is to avoid subdiagnostics overwriting an existing diagnostic arg. + debug_assert!( + !self.args.contains_key(&name) || self.args.get(&name) == Some(&value), + "arg {} already exists", + name + ); + self.args.insert(name, value); + } + + pub fn remove_arg(&mut self, name: &str) { + self.args.swap_remove(name); + } + + pub fn store_args(&mut self) { + self.reserved_args = self.args.clone(); + } + + pub fn restore_args(&mut self) { + self.args = std::mem::take(&mut self.reserved_args); } /// Fields used for Hash, and PartialEq trait. @@ -1423,6 +1447,12 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self.downgrade_to_delayed_bug(); self.emit() } + + pub fn remove_arg(&mut self, name: &str) { + if let Some(diag) = self.diag.as_mut() { + diag.remove_arg(name); + } + } } /// Destructor bomb: every `Diag` must be consumed (emitted, cancelled, etc.) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 6ab6f96079eb..e333de4b660b 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -35,10 +35,10 @@ use crate::snippet::{ }; use crate::styled_buffer::StyledBuffer; use crate::timings::TimingRecord; -use crate::translation::{Translate, to_fluent_args}; +use crate::translation::{Translator, to_fluent_args}; use crate::{ - CodeSuggestion, DiagInner, DiagMessage, ErrCode, FluentBundle, LazyFallbackBundle, Level, - MultiSpan, Subdiag, SubstitutionHighlight, SuggestionStyle, TerminalUrl, + CodeSuggestion, DiagInner, DiagMessage, ErrCode, Level, MultiSpan, Subdiag, + SubstitutionHighlight, SuggestionStyle, TerminalUrl, }; /// Default column width, used in tests and when terminal dimensions cannot be determined. @@ -175,7 +175,7 @@ const ANONYMIZED_LINE_NUM: &str = "LL"; pub type DynEmitter = dyn Emitter + DynSend; /// Emitter trait for emitting errors and other structured information. -pub trait Emitter: Translate { +pub trait Emitter { /// Emit a structured diagnostic. fn emit_diagnostic(&mut self, diag: DiagInner, registry: &Registry); @@ -212,6 +212,8 @@ pub trait Emitter: Translate { fn source_map(&self) -> Option<&SourceMap>; + fn translator(&self) -> &Translator; + /// Formats the substitutions of the primary_span /// /// There are a lot of conditions to this method, but in short: @@ -224,13 +226,17 @@ pub trait Emitter: Translate { /// * If the current `DiagInner` has multiple suggestions, /// we leave `primary_span` and the suggestions untouched. fn primary_span_formatted( - &mut self, + &self, primary_span: &mut MultiSpan, suggestions: &mut Vec, fluent_args: &FluentArgs<'_>, ) { if let Some((sugg, rest)) = suggestions.split_first() { - let msg = self.translate_message(&sugg.msg, fluent_args).map_err(Report::new).unwrap(); + let msg = self + .translator() + .translate_message(&sugg.msg, fluent_args) + .map_err(Report::new) + .unwrap(); if rest.is_empty() // ^ if there is only one suggestion // don't display multi-suggestions as labels @@ -491,16 +497,6 @@ pub trait Emitter: Translate { } } -impl Translate for HumanEmitter { - fn fluent_bundle(&self) -> Option<&FluentBundle> { - self.fluent_bundle.as_deref() - } - - fn fallback_fluent_bundle(&self) -> &FluentBundle { - &self.fallback_bundle - } -} - impl Emitter for HumanEmitter { fn source_map(&self) -> Option<&SourceMap> { self.sm.as_deref() @@ -538,25 +534,41 @@ impl Emitter for HumanEmitter { fn supports_color(&self) -> bool { self.dst.supports_color() } + + fn translator(&self) -> &Translator { + &self.translator + } } /// An emitter that does nothing when emitting a non-fatal diagnostic. /// Fatal diagnostics are forwarded to `fatal_emitter` to avoid silent /// failures of rustc, as witnessed e.g. in issue #89358. -pub struct SilentEmitter { +pub struct FatalOnlyEmitter { pub fatal_emitter: Box, pub fatal_note: Option, - pub emit_fatal_diagnostic: bool, } -impl Translate for SilentEmitter { - fn fluent_bundle(&self) -> Option<&FluentBundle> { +impl Emitter for FatalOnlyEmitter { + fn source_map(&self) -> Option<&SourceMap> { None } - fn fallback_fluent_bundle(&self) -> &FluentBundle { - self.fatal_emitter.fallback_fluent_bundle() + fn emit_diagnostic(&mut self, mut diag: DiagInner, registry: &Registry) { + if diag.level == Level::Fatal { + if let Some(fatal_note) = &self.fatal_note { + diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new()); + } + self.fatal_emitter.emit_diagnostic(diag, registry); + } } + + fn translator(&self) -> &Translator { + self.fatal_emitter.translator() + } +} + +pub struct SilentEmitter { + pub translator: Translator, } impl Emitter for SilentEmitter { @@ -564,13 +576,10 @@ impl Emitter for SilentEmitter { None } - fn emit_diagnostic(&mut self, mut diag: DiagInner, registry: &Registry) { - if self.emit_fatal_diagnostic && diag.level == Level::Fatal { - if let Some(fatal_note) = &self.fatal_note { - diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new()); - } - self.fatal_emitter.emit_diagnostic(diag, registry); - } + fn emit_diagnostic(&mut self, _diag: DiagInner, _registry: &Registry) {} + + fn translator(&self) -> &Translator { + &self.translator } } @@ -615,9 +624,8 @@ pub struct HumanEmitter { #[setters(skip)] dst: IntoDynSyncSend, sm: Option>, - fluent_bundle: Option>, #[setters(skip)] - fallback_bundle: LazyFallbackBundle, + translator: Translator, short_message: bool, ui_testing: bool, ignored_directories_in_source_blocks: Vec, @@ -637,12 +645,11 @@ pub(crate) struct FileWithAnnotatedLines { } impl HumanEmitter { - pub fn new(dst: Destination, fallback_bundle: LazyFallbackBundle) -> HumanEmitter { + pub fn new(dst: Destination, translator: Translator) -> HumanEmitter { HumanEmitter { dst: IntoDynSyncSend(dst), sm: None, - fluent_bundle: None, - fallback_bundle, + translator, short_message: false, ui_testing: false, ignored_directories_in_source_blocks: Vec::new(), @@ -1433,7 +1440,7 @@ impl HumanEmitter { // very *weird* formats // see? for (text, style) in msgs.iter() { - let text = self.translate_message(text, args).map_err(Report::new).unwrap(); + let text = self.translator.translate_message(text, args).map_err(Report::new).unwrap(); let text = &normalize_whitespace(&text); let lines = text.split('\n').collect::>(); if lines.len() > 1 { @@ -1528,7 +1535,8 @@ impl HumanEmitter { } let mut line = 0; for (text, style) in msgs.iter() { - let text = self.translate_message(text, args).map_err(Report::new).unwrap(); + let text = + self.translator.translate_message(text, args).map_err(Report::new).unwrap(); // Account for newlines to align output to its label. for text in normalize_whitespace(&text).lines() { buffer.append( @@ -1560,7 +1568,7 @@ impl HumanEmitter { .into_iter() .filter_map(|label| match label.label { Some(msg) if label.is_primary => { - let text = self.translate_message(&msg, args).ok()?; + let text = self.translator.translate_message(&msg, args).ok()?; if !text.trim().is_empty() { Some(text.to_string()) } else { None } } _ => None, @@ -3104,7 +3112,11 @@ impl FileWithAnnotatedLines { let label = label.as_ref().map(|m| { normalize_whitespace( - &emitter.translate_message(m, args).map_err(Report::new).unwrap(), + &emitter + .translator() + .translate_message(m, args) + .map_err(Report::new) + .unwrap(), ) }); diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index d67e2ba2d60e..4348610be0af 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -32,11 +32,8 @@ use crate::emitter::{ }; use crate::registry::Registry; use crate::timings::{TimingRecord, TimingSection}; -use crate::translation::{Translate, to_fluent_args}; -use crate::{ - CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, Subdiag, Suggestions, - TerminalUrl, -}; +use crate::translation::{Translator, to_fluent_args}; +use crate::{CodeSuggestion, MultiSpan, SpanLabel, Subdiag, Suggestions, TerminalUrl}; #[cfg(test)] mod tests; @@ -47,9 +44,8 @@ pub struct JsonEmitter { dst: IntoDynSyncSend>, #[setters(skip)] sm: Option>, - fluent_bundle: Option>, #[setters(skip)] - fallback_bundle: LazyFallbackBundle, + translator: Translator, #[setters(skip)] pretty: bool, ui_testing: bool, @@ -67,7 +63,7 @@ impl JsonEmitter { pub fn new( dst: Box, sm: Option>, - fallback_bundle: LazyFallbackBundle, + translator: Translator, pretty: bool, json_rendered: HumanReadableErrorType, color_config: ColorConfig, @@ -75,8 +71,7 @@ impl JsonEmitter { JsonEmitter { dst: IntoDynSyncSend(dst), sm, - fluent_bundle: None, - fallback_bundle, + translator, pretty, ui_testing: false, ignored_directories_in_source_blocks: Vec::new(), @@ -110,16 +105,6 @@ enum EmitTyped<'a> { UnusedExtern(UnusedExterns<'a>), } -impl Translate for JsonEmitter { - fn fluent_bundle(&self) -> Option<&FluentBundle> { - self.fluent_bundle.as_deref() - } - - fn fallback_fluent_bundle(&self) -> &FluentBundle { - &self.fallback_bundle - } -} - impl Emitter for JsonEmitter { fn emit_diagnostic(&mut self, diag: crate::DiagInner, registry: &Registry) { let data = Diagnostic::from_errors_diagnostic(diag, self, registry); @@ -144,6 +129,7 @@ impl Emitter for JsonEmitter { }; let name = match record.section { TimingSection::Linking => "link", + TimingSection::Codegen => "codegen", }; let data = SectionTimestamp { name, event, timestamp: record.timestamp }; let result = self.emit(EmitTyped::SectionTiming(data)); @@ -194,6 +180,10 @@ impl Emitter for JsonEmitter { fn should_show_explain(&self) -> bool { !self.json_rendered.short() } + + fn translator(&self) -> &Translator { + &self.translator + } } // The following data types are provided just for serialisation. @@ -324,7 +314,7 @@ impl Diagnostic { let args = to_fluent_args(diag.args.iter()); let sugg_to_diag = |sugg: &CodeSuggestion| { let translated_message = - je.translate_message(&sugg.msg, &args).map_err(Report::new).unwrap(); + je.translator.translate_message(&sugg.msg, &args).map_err(Report::new).unwrap(); Diagnostic { message: translated_message.to_string(), code: None, @@ -368,7 +358,7 @@ impl Diagnostic { } } - let translated_message = je.translate_messages(&diag.messages, &args); + let translated_message = je.translator.translate_messages(&diag.messages, &args); let code = if let Some(code) = diag.code { Some(DiagnosticCode { @@ -396,10 +386,9 @@ impl Diagnostic { ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)), ColorConfig::Never => {} } - HumanEmitter::new(dst, Arc::clone(&je.fallback_bundle)) + HumanEmitter::new(dst, je.translator.clone()) .short_message(short) .sm(je.sm.clone()) - .fluent_bundle(je.fluent_bundle.clone()) .diagnostic_width(je.diagnostic_width) .macro_backtrace(je.macro_backtrace) .track_diagnostics(je.track_diagnostics) @@ -430,7 +419,7 @@ impl Diagnostic { args: &FluentArgs<'_>, je: &JsonEmitter, ) -> Diagnostic { - let translated_message = je.translate_messages(&subdiag.messages, args); + let translated_message = je.translator.translate_messages(&subdiag.messages, args); Diagnostic { message: translated_message.to_string(), code: None, @@ -454,7 +443,7 @@ impl DiagnosticSpan { span.is_primary, span.label .as_ref() - .map(|m| je.translate_message(m, args).unwrap()) + .map(|m| je.translator.translate_message(m, args).unwrap()) .map(|m| m.to_string()), suggestion, je, diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs index 40973e8e5d8a..8cf81f467d84 100644 --- a/compiler/rustc_errors/src/json/tests.rs +++ b/compiler/rustc_errors/src/json/tests.rs @@ -41,14 +41,14 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) { rustc_span::create_default_session_globals_then(|| { let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned()); - let fallback_bundle = - crate::fallback_fluent_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false); + let translator = + Translator::with_fallback_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false); let output = Arc::new(Mutex::new(Vec::new())); let je = JsonEmitter::new( Box::new(Shared { data: output.clone() }), Some(sm), - fallback_bundle, + translator, true, // pretty HumanReadableErrorType::Short, ColorConfig::Never, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 0bd259366def..207aed8c7554 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -748,40 +748,10 @@ impl DiagCtxt { Self { inner: Lock::new(DiagCtxtInner::new(emitter)) } } - pub fn make_silent(&self, fatal_note: Option, emit_fatal_diagnostic: bool) { - // An empty type that implements `Emitter` to temporarily swap in place of the real one, - // which will be used in constructing its replacement. - struct FalseEmitter; - - impl Emitter for FalseEmitter { - fn emit_diagnostic(&mut self, _: DiagInner, _: &Registry) { - unimplemented!("false emitter must only used during `make_silent`") - } - - fn source_map(&self) -> Option<&SourceMap> { - unimplemented!("false emitter must only used during `make_silent`") - } - } - - impl translation::Translate for FalseEmitter { - fn fluent_bundle(&self) -> Option<&FluentBundle> { - unimplemented!("false emitter must only used during `make_silent`") - } - - fn fallback_fluent_bundle(&self) -> &FluentBundle { - unimplemented!("false emitter must only used during `make_silent`") - } - } - + pub fn make_silent(&self) { let mut inner = self.inner.borrow_mut(); - let mut prev_emitter = Box::new(FalseEmitter) as Box; - std::mem::swap(&mut inner.emitter, &mut prev_emitter); - let new_emitter = Box::new(emitter::SilentEmitter { - fatal_emitter: prev_emitter, - fatal_note, - emit_fatal_diagnostic, - }); - inner.emitter = new_emitter; + let translator = inner.emitter.translator().clone(); + inner.emitter = Box::new(emitter::SilentEmitter { translator }); } pub fn set_emitter(&self, emitter: Box) { @@ -1771,7 +1741,12 @@ impl DiagCtxtInner { args: impl Iterator>, ) -> String { let args = crate::translation::to_fluent_args(args); - self.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string() + self.emitter + .translator() + .translate_message(&message, &args) + .map_err(Report::new) + .unwrap() + .to_string() } fn eagerly_translate_for_subdiag( diff --git a/compiler/rustc_errors/src/tests.rs b/compiler/rustc_errors/src/tests.rs index 376fd24d57ba..34ebac0fde11 100644 --- a/compiler/rustc_errors/src/tests.rs +++ b/compiler/rustc_errors/src/tests.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, LazyLock}; + use rustc_data_structures::sync::IntoDynSyncSend; use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError}; use rustc_error_messages::{DiagMessage, langid}; @@ -5,23 +7,9 @@ use rustc_error_messages::{DiagMessage, langid}; use crate::FluentBundle; use crate::error::{TranslateError, TranslateErrorKind}; use crate::fluent_bundle::*; -use crate::translation::Translate; +use crate::translation::Translator; -struct Dummy { - bundle: FluentBundle, -} - -impl Translate for Dummy { - fn fluent_bundle(&self) -> Option<&FluentBundle> { - None - } - - fn fallback_fluent_bundle(&self) -> &FluentBundle { - &self.bundle - } -} - -fn make_dummy(ftl: &'static str) -> Dummy { +fn make_translator(ftl: &'static str) -> Translator { let resource = FluentResource::try_new(ftl.into()).expect("Failed to parse an FTL string."); let langid_en = langid!("en-US"); @@ -33,12 +21,15 @@ fn make_dummy(ftl: &'static str) -> Dummy { bundle.add_resource(resource).expect("Failed to add FTL resources to the bundle."); - Dummy { bundle } + Translator { + fluent_bundle: None, + fallback_fluent_bundle: Arc::new(LazyLock::new(Box::new(|| bundle))), + } } #[test] fn wellformed_fluent() { - let dummy = make_dummy("mir_build_borrow_of_moved_value = borrow of moved value + let translator = make_translator("mir_build_borrow_of_moved_value = borrow of moved value .label = value moved into `{$name}` here .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait .value_borrowed_label = value borrowed here after move @@ -54,7 +45,7 @@ fn wellformed_fluent() { ); assert_eq!( - dummy.translate_message(&message, &args).unwrap(), + translator.translate_message(&message, &args).unwrap(), "borrow this binding in the pattern to avoid moving the value" ); } @@ -66,7 +57,7 @@ fn wellformed_fluent() { ); assert_eq!( - dummy.translate_message(&message, &args).unwrap(), + translator.translate_message(&message, &args).unwrap(), "value borrowed here after move" ); } @@ -78,7 +69,7 @@ fn wellformed_fluent() { ); assert_eq!( - dummy.translate_message(&message, &args).unwrap(), + translator.translate_message(&message, &args).unwrap(), "move occurs because `\u{2068}Foo\u{2069}` has type `\u{2068}std::string::String\u{2069}` which does not implement the `Copy` trait" ); @@ -89,7 +80,7 @@ fn wellformed_fluent() { ); assert_eq!( - dummy.translate_message(&message, &args).unwrap(), + translator.translate_message(&message, &args).unwrap(), "value moved into `\u{2068}Foo\u{2069}` here" ); } @@ -98,7 +89,7 @@ fn wellformed_fluent() { #[test] fn misformed_fluent() { - let dummy = make_dummy("mir_build_borrow_of_moved_value = borrow of moved value + let translator = make_translator("mir_build_borrow_of_moved_value = borrow of moved value .label = value moved into `{name}` here .occurs_because_label = move occurs because `{$oops}` has type `{$ty}` which does not implement the `Copy` trait .suggestion = borrow this binding in the pattern to avoid moving the value"); @@ -112,7 +103,7 @@ fn misformed_fluent() { Some("value_borrowed_label".into()), ); - let err = dummy.translate_message(&message, &args).unwrap_err(); + let err = translator.translate_message(&message, &args).unwrap_err(); assert!( matches!( &err, @@ -141,7 +132,7 @@ fn misformed_fluent() { Some("label".into()), ); - let err = dummy.translate_message(&message, &args).unwrap_err(); + let err = translator.translate_message(&message, &args).unwrap_err(); if let TranslateError::Two { primary: box TranslateError::One { kind: TranslateErrorKind::PrimaryBundleMissing, .. }, fallback: box TranslateError::One { kind: TranslateErrorKind::Fluent { errs }, .. }, @@ -168,7 +159,7 @@ fn misformed_fluent() { Some("occurs_because_label".into()), ); - let err = dummy.translate_message(&message, &args).unwrap_err(); + let err = translator.translate_message(&message, &args).unwrap_err(); if let TranslateError::Two { primary: box TranslateError::One { kind: TranslateErrorKind::PrimaryBundleMissing, .. }, fallback: box TranslateError::One { kind: TranslateErrorKind::Fluent { errs }, .. }, diff --git a/compiler/rustc_errors/src/timings.rs b/compiler/rustc_errors/src/timings.rs index 27fc9df8d796..0d82f3e8db8b 100644 --- a/compiler/rustc_errors/src/timings.rs +++ b/compiler/rustc_errors/src/timings.rs @@ -1,10 +1,15 @@ use std::time::Instant; +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sync::Lock; + use crate::DiagCtxtHandle; /// A high-level section of the compilation process. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum TimingSection { + /// Time spent doing codegen. + Codegen, /// Time spent linking. Linking, } @@ -36,23 +41,59 @@ pub struct TimingSectionHandler { /// Time when the compilation session started. /// If `None`, timing is disabled. origin: Option, + /// Sanity check to ensure that we open and close sections correctly. + opened_sections: Lock>, } impl TimingSectionHandler { pub fn new(enabled: bool) -> Self { let origin = if enabled { Some(Instant::now()) } else { None }; - Self { origin } + Self { origin, opened_sections: Lock::new(FxHashSet::default()) } } /// Returns a RAII guard that will immediately emit a start the provided section, and then emit /// its end when it is dropped. - pub fn start_section<'a>( + pub fn section_guard<'a>( &self, diag_ctxt: DiagCtxtHandle<'a>, section: TimingSection, ) -> TimingSectionGuard<'a> { + if self.is_enabled() && self.opened_sections.borrow().contains(§ion) { + diag_ctxt + .bug(format!("Section `{section:?}` was started again before it was finished")); + } + TimingSectionGuard::create(diag_ctxt, section, self.origin) } + + /// Start the provided section. + pub fn start_section(&self, diag_ctxt: DiagCtxtHandle<'_>, section: TimingSection) { + if let Some(origin) = self.origin { + let mut opened = self.opened_sections.borrow_mut(); + if !opened.insert(section) { + diag_ctxt + .bug(format!("Section `{section:?}` was started again before it was finished")); + } + + diag_ctxt.emit_timing_section_start(TimingRecord::from_origin(origin, section)); + } + } + + /// End the provided section. + pub fn end_section(&self, diag_ctxt: DiagCtxtHandle<'_>, section: TimingSection) { + if let Some(origin) = self.origin { + let mut opened = self.opened_sections.borrow_mut(); + if !opened.remove(§ion) { + diag_ctxt.bug(format!("Section `{section:?}` was ended before being started")); + } + + diag_ctxt.emit_timing_section_end(TimingRecord::from_origin(origin, section)); + } + } + + fn is_enabled(&self) -> bool { + self.origin.is_some() + } } /// RAII wrapper for starting and ending section timings. diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index 156f5e5d26e6..c0bcec093c7e 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -1,8 +1,9 @@ use std::borrow::Cow; use std::env; use std::error::Report; +use std::sync::Arc; -pub use rustc_error_messages::FluentArgs; +pub use rustc_error_messages::{FluentArgs, LazyFallbackBundle}; use tracing::{debug, trace}; use crate::error::{TranslateError, TranslateErrorKind}; @@ -28,19 +29,33 @@ pub fn to_fluent_args<'iter>(iter: impl Iterator>) -> Flue args } -pub trait Translate { - /// Return `FluentBundle` with localized diagnostics for the locale requested by the user. If no - /// language was requested by the user then this will be `None` and `fallback_fluent_bundle` - /// should be used. - fn fluent_bundle(&self) -> Option<&FluentBundle>; - +#[derive(Clone)] +pub struct Translator { + /// Localized diagnostics for the locale requested by the user. If no language was requested by + /// the user then this will be `None` and `fallback_fluent_bundle` should be used. + pub fluent_bundle: Option>, /// Return `FluentBundle` with localized diagnostics for the default locale of the compiler. /// Used when the user has not requested a specific language or when a localized diagnostic is /// unavailable for the requested locale. - fn fallback_fluent_bundle(&self) -> &FluentBundle; + pub fallback_fluent_bundle: LazyFallbackBundle, +} + +impl Translator { + pub fn with_fallback_bundle( + resources: Vec<&'static str>, + with_directionality_markers: bool, + ) -> Translator { + Translator { + fluent_bundle: None, + fallback_fluent_bundle: crate::fallback_fluent_bundle( + resources, + with_directionality_markers, + ), + } + } /// Convert `DiagMessage`s to a string, performing translation if necessary. - fn translate_messages( + pub fn translate_messages( &self, messages: &[(DiagMessage, Style)], args: &FluentArgs<'_>, @@ -54,7 +69,7 @@ pub trait Translate { } /// Convert a `DiagMessage` to a string, performing translation if necessary. - fn translate_message<'a>( + pub fn translate_message<'a>( &'a self, message: &'a DiagMessage, args: &'a FluentArgs<'_>, @@ -91,7 +106,7 @@ pub trait Translate { }; try { - match self.fluent_bundle().map(|b| translate_with_bundle(b)) { + match self.fluent_bundle.as_ref().map(|b| translate_with_bundle(b)) { // The primary bundle was present and translation succeeded Some(Ok(t)) => t, @@ -102,7 +117,7 @@ pub trait Translate { primary @ TranslateError::One { kind: TranslateErrorKind::MessageMissing, .. }, - )) => translate_with_bundle(self.fallback_fluent_bundle()) + )) => translate_with_bundle(&self.fallback_fluent_bundle) .map_err(|fallback| primary.and(fallback))?, // Always yeet out for errors on debug (unless @@ -118,11 +133,11 @@ pub trait Translate { // ..otherwise, for end users, an error about this wouldn't be useful or actionable, so // just hide it and try with the fallback bundle. - Some(Err(primary)) => translate_with_bundle(self.fallback_fluent_bundle()) + Some(Err(primary)) => translate_with_bundle(&self.fallback_fluent_bundle) .map_err(|fallback| primary.and(fallback))?, // The primary bundle is missing, proceed to the fallback bundle - None => translate_with_bundle(self.fallback_fluent_bundle()) + None => translate_with_bundle(&self.fallback_fluent_bundle) .map_err(|fallback| TranslateError::primary(identifier, args).and(fallback))?, } } diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 8b7c47dad991..b7555bba28ec 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -62,7 +62,7 @@ expand_feature_not_allowed = expand_feature_removed = feature has been removed .label = feature has been removed - .note = removed in {$removed_rustc_version} (you are using {$current_rustc_version}){$pull_note} + .note = removed in {$removed_rustc_version}{$pull_note} .reason = {$reason} expand_glob_delegation_outside_impls = diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 9a359e9b0310..170ac39d1ec3 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -92,7 +92,6 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) - span: mi.span(), reason: f.reason.map(|reason| FeatureRemovedReason { reason }), removed_rustc_version: f.feature.since, - current_rustc_version: sess.cfg_version, pull_note, }); continue; diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index ec0af67c0463..fe4d2af97a0d 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -162,7 +162,6 @@ pub(crate) struct FeatureRemoved<'a> { #[subdiagnostic] pub reason: Option>, pub removed_rustc_version: &'a str, - pub current_rustc_version: &'a str, pub pull_note: String, } @@ -183,12 +182,12 @@ pub(crate) struct FeatureNotAllowed { #[derive(Diagnostic)] #[diag(expand_recursion_limit_reached)] #[help] -pub(crate) struct RecursionLimitReached<'a> { +pub(crate) struct RecursionLimitReached { #[primary_span] pub span: Span, pub descr: String, pub suggested_limit: Limit, - pub crate_name: &'a str, + pub crate_name: Symbol, } #[derive(Diagnostic)] @@ -444,7 +443,7 @@ pub(crate) struct InvalidFragmentSpecifier { #[primary_span] pub span: Span, pub fragment: Ident, - pub help: String, + pub help: &'static str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 9fd524ef45cd..0474413e7626 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -26,7 +26,7 @@ use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS}; use rustc_session::parse::feature_err; use rustc_session::{Limit, Session}; use rustc_span::hygiene::SyntaxContext; -use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, sym}; +use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, Symbol, sym}; use smallvec::SmallVec; use crate::base::*; @@ -86,7 +86,7 @@ macro_rules! ast_fragments { } } - fn make_from<'a>(self, result: Box) -> Option { + fn make_from(self, result: Box) -> Option { match self { AstFragmentKind::OptExpr => result.make_expr().map(Some).map(AstFragment::OptExpr), @@ -136,7 +136,7 @@ macro_rules! ast_fragments { T::fragment_to_output(self) } - pub(crate) fn mut_visit_with(&mut self, vis: &mut F) { + pub(crate) fn mut_visit_with(&mut self, vis: &mut impl MutVisitor) { match self { AstFragment::OptExpr(opt_expr) => { if let Some(expr) = opt_expr.take() { @@ -316,9 +316,9 @@ impl AstFragmentKind { } } - pub(crate) fn expect_from_annotatables>( + pub(crate) fn expect_from_annotatables( self, - items: I, + items: impl IntoIterator, ) -> AstFragment { let mut items = items.into_iter(); match self { @@ -473,7 +473,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let dir_path = file_path.parent().unwrap_or(&file_path).to_owned(); self.cx.root_path = dir_path.clone(); self.cx.current_expansion.module = Rc::new(ModuleData { - mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)], + mod_path: vec![Ident::with_dummy_span(self.cx.ecfg.crate_name)], file_path_stack: vec![file_path], dir_path, }); @@ -689,7 +689,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { span: expn_data.call_site, descr: expn_data.kind.descr(), suggested_limit, - crate_name: &self.cx.ecfg.crate_name, + crate_name: self.cx.ecfg.crate_name, }); self.cx.trace_macros_diag(); @@ -1218,10 +1218,10 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { fn descr() -> &'static str { unreachable!() } - fn walk_flat_map(self, _visitor: &mut V) -> Self::OutputTy { + fn walk_flat_map(self, _collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { unreachable!() } - fn walk(&mut self, _visitor: &mut V) { + fn walk(&mut self, _collector: &mut InvocationCollector<'_, '_>) { unreachable!() } fn is_mac_call(&self) -> bool { @@ -1276,8 +1276,8 @@ impl InvocationCollectorNode for P { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_items() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_item(visitor, self) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_item(collector, self) } fn is_mac_call(&self) -> bool { matches!(self.kind, ItemKind::MacCall(..)) @@ -1431,8 +1431,8 @@ impl InvocationCollectorNode for AstNodeWrapper, TraitItemTag> fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_trait_items() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Trait) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_assoc_item(collector, self.wrapped, AssocCtxt::Trait) } fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) @@ -1472,8 +1472,8 @@ impl InvocationCollectorNode for AstNodeWrapper, ImplItemTag> fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_impl_items() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl { of_trait: false }) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_assoc_item(collector, self.wrapped, AssocCtxt::Impl { of_trait: false }) } fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) @@ -1513,8 +1513,8 @@ impl InvocationCollectorNode for AstNodeWrapper, TraitImplItem fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_trait_impl_items() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl { of_trait: true }) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_assoc_item(collector, self.wrapped, AssocCtxt::Impl { of_trait: true }) } fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) @@ -1551,8 +1551,8 @@ impl InvocationCollectorNode for P { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_foreign_items() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_foreign_item(visitor, self) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_foreign_item(collector, self) } fn is_mac_call(&self) -> bool { matches!(self.kind, ForeignItemKind::MacCall(..)) @@ -1573,8 +1573,8 @@ impl InvocationCollectorNode for ast::Variant { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_variants() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_variant(visitor, self) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_variant(collector, self) } } @@ -1586,8 +1586,8 @@ impl InvocationCollectorNode for ast::WherePredicate { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_where_predicates() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_where_predicate(visitor, self) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_where_predicate(collector, self) } } @@ -1599,8 +1599,8 @@ impl InvocationCollectorNode for ast::FieldDef { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_field_defs() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_field_def(visitor, self) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_field_def(collector, self) } } @@ -1612,8 +1612,8 @@ impl InvocationCollectorNode for ast::PatField { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_pat_fields() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_pat_field(visitor, self) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_pat_field(collector, self) } } @@ -1625,8 +1625,8 @@ impl InvocationCollectorNode for ast::ExprField { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_expr_fields() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_expr_field(visitor, self) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_expr_field(collector, self) } } @@ -1638,8 +1638,8 @@ impl InvocationCollectorNode for ast::Param { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_params() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_param(visitor, self) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_param(collector, self) } } @@ -1651,8 +1651,8 @@ impl InvocationCollectorNode for ast::GenericParam { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_generic_params() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_generic_param(visitor, self) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_generic_param(collector, self) } } @@ -1664,8 +1664,8 @@ impl InvocationCollectorNode for ast::Arm { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_arms() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_arm(visitor, self) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_arm(collector, self) } } @@ -1677,8 +1677,8 @@ impl InvocationCollectorNode for ast::Stmt { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_stmts() } - fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_stmt(visitor, self) + fn walk_flat_map(self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_flat_map_stmt(collector, self) } fn is_mac_call(&self) -> bool { match &self.kind { @@ -1751,8 +1751,8 @@ impl InvocationCollectorNode for ast::Crate { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_crate() } - fn walk(&mut self, visitor: &mut V) { - walk_crate(visitor, self) + fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) { + walk_crate(collector, self) } fn expand_cfg_false( &mut self, @@ -1777,8 +1777,8 @@ impl InvocationCollectorNode for ast::Ty { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_ty() } - fn walk(&mut self, visitor: &mut V) { - walk_ty(visitor, self) + fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) { + walk_ty(collector, self) } fn is_mac_call(&self) -> bool { matches!(self.kind, ast::TyKind::MacCall(..)) @@ -1800,8 +1800,8 @@ impl InvocationCollectorNode for ast::Pat { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_pat() } - fn walk(&mut self, visitor: &mut V) { - walk_pat(visitor, self) + fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) { + walk_pat(collector, self) } fn is_mac_call(&self) -> bool { matches!(self.kind, PatKind::MacCall(..)) @@ -1826,8 +1826,8 @@ impl InvocationCollectorNode for ast::Expr { fn descr() -> &'static str { "an expression" } - fn walk(&mut self, visitor: &mut V) { - walk_expr(visitor, self) + fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) { + walk_expr(collector, self) } fn is_mac_call(&self) -> bool { matches!(self.kind, ExprKind::MacCall(..)) @@ -1850,8 +1850,8 @@ impl InvocationCollectorNode for AstNodeWrapper, OptExprTag> { fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_opt_expr() } - fn walk_flat_map(mut self, visitor: &mut V) -> Self::OutputTy { - walk_expr(visitor, &mut self.wrapped); + fn walk_flat_map(mut self, collector: &mut InvocationCollector<'_, '_>) -> Self::OutputTy { + walk_expr(collector, &mut self.wrapped); Some(self.wrapped) } fn is_mac_call(&self) -> bool { @@ -1873,20 +1873,20 @@ impl InvocationCollectorNode for AstNodeWrapper, OptExprTag> { /// It can be removed once that feature is stabilized. struct MethodReceiverTag; -impl InvocationCollectorNode for AstNodeWrapper, MethodReceiverTag> { - type OutputTy = Self; +impl InvocationCollectorNode for AstNodeWrapper { + type OutputTy = AstNodeWrapper, MethodReceiverTag>; const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr; fn descr() -> &'static str { "an expression" } fn to_annotatable(self) -> Annotatable { - Annotatable::Expr(self.wrapped) + Annotatable::Expr(P(self.wrapped)) } fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { AstNodeWrapper::new(fragment.make_method_receiver_expr(), MethodReceiverTag) } - fn walk(&mut self, visitor: &mut V) { - walk_expr(visitor, &mut self.wrapped) + fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) { + walk_expr(collector, &mut self.wrapped) } fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, ast::ExprKind::MacCall(..)) @@ -1983,9 +1983,9 @@ impl DummyAstNode for ast::Expr { } } -impl DummyAstNode for AstNodeWrapper, MethodReceiverTag> { +impl DummyAstNode for AstNodeWrapper { fn dummy() -> Self { - AstNodeWrapper::new(P(ast::Expr::dummy()), MethodReceiverTag) + AstNodeWrapper::new(ast::Expr::dummy(), MethodReceiverTag) } } @@ -2431,7 +2431,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { self.visit_node(node) } - fn visit_method_receiver_expr(&mut self, node: &mut P) { + fn visit_method_receiver_expr(&mut self, node: &mut ast::Expr) { self.visit_node(AstNodeWrapper::from_mut(node, MethodReceiverTag)) } @@ -2458,7 +2458,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } pub struct ExpansionConfig<'feat> { - pub crate_name: String, + pub crate_name: Symbol, pub features: &'feat Features, pub recursion_limit: Limit, pub trace_mac: bool, @@ -2471,7 +2471,7 @@ pub struct ExpansionConfig<'feat> { } impl ExpansionConfig<'_> { - pub fn default(crate_name: String, features: &Features) -> ExpansionConfig<'_> { + pub fn default(crate_name: Symbol, features: &Features) -> ExpansionConfig<'_> { ExpansionConfig { crate_name, features, diff --git a/compiler/rustc_expand/src/mbe.rs b/compiler/rustc_expand/src/mbe.rs index 4ff8c02bcdb8..3082c881a7a6 100644 --- a/compiler/rustc_expand/src/mbe.rs +++ b/compiler/rustc_expand/src/mbe.rs @@ -78,7 +78,13 @@ enum TokenTree { /// only covers the ident, e.g. `var`.) MetaVar(Span, Ident), /// e.g., `$var:expr`. Only appears on the LHS. - MetaVarDecl(Span, Ident /* name to bind */, Option), + MetaVarDecl { + span: Span, + /// Name to bind. + name: Ident, + /// The fragment specifier. + kind: NonterminalKind, + }, /// A meta-variable expression inside `${...}`. MetaVarExpr(DelimSpan, MetaVarExpr), } @@ -102,7 +108,7 @@ impl TokenTree { match *self { TokenTree::Token(Token { span, .. }) | TokenTree::MetaVar(span, _) - | TokenTree::MetaVarDecl(span, _, _) => span, + | TokenTree::MetaVarDecl { span, .. } => span, TokenTree::Delimited(span, ..) | TokenTree::MetaVarExpr(span, _) | TokenTree::Sequence(span, _) => span.entire(), diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 698492f42e28..99aa376626d4 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -24,6 +24,7 @@ pub(super) fn failed_to_match_macro( arg: TokenStream, lhses: &[Vec], ) -> (Span, ErrorGuaranteed) { + debug!("failed to match macro"); // An error occurred, try the expansion again, tracking the expansion closely for better // diagnostics. let mut tracker = CollectTrackerAndEmitter::new(psess.dcx(), sp); diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 3cd803c3e848..dc2d46c4a141 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -117,7 +117,6 @@ use rustc_session::parse::ParseSess; use rustc_span::{ErrorGuaranteed, MacroRulesNormalizedIdent, Span, kw}; use smallvec::SmallVec; -use super::quoted::VALID_FRAGMENT_NAMES_MSG; use crate::errors; use crate::mbe::{KleeneToken, TokenTree}; @@ -263,14 +262,7 @@ fn check_binders( } } // Similarly, this can only happen when checking a toplevel macro. - TokenTree::MetaVarDecl(span, name, kind) => { - if kind.is_none() && node_id != DUMMY_NODE_ID { - psess.dcx().emit_err(errors::MissingFragmentSpecifier { - span, - add_span: span.shrink_to_hi(), - valid: VALID_FRAGMENT_NAMES_MSG, - }); - } + TokenTree::MetaVarDecl { span, name, .. } => { if !macros.is_empty() { psess.dcx().span_bug(span, "unexpected MetaVarDecl in nested lhs"); } @@ -339,7 +331,7 @@ fn check_occurrences( ) { match *rhs { TokenTree::Token(..) => {} - TokenTree::MetaVarDecl(span, _name, _kind) => { + TokenTree::MetaVarDecl { span, .. } => { psess.dcx().span_bug(span, "unexpected MetaVarDecl in rhs") } TokenTree::MetaVar(span, name) => { diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index c78beb40688f..802e43209a51 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -122,7 +122,7 @@ pub(crate) enum MatcherLoc { MetaVarDecl { span: Span, bind: Ident, - kind: Option, + kind: NonterminalKind, next_metavar: usize, seq_depth: usize, }, @@ -151,12 +151,7 @@ impl Display for MatcherLoc { write!(f, "{}", token_descr(token)) } MatcherLoc::MetaVarDecl { bind, kind, .. } => { - write!(f, "meta-variable `${bind}")?; - if let Some(kind) = kind { - write!(f, ":{kind}")?; - } - write!(f, "`")?; - Ok(()) + write!(f, "meta-variable `${bind}:{kind}`") } MatcherLoc::Eof => f.write_str("end of macro"), @@ -220,7 +215,7 @@ pub(super) fn compute_locs(matcher: &[TokenTree]) -> Vec { seq_depth, }; } - &TokenTree::MetaVarDecl(span, bind, kind) => { + &TokenTree::MetaVarDecl { span, name: bind, kind } => { locs.push(MatcherLoc::MetaVarDecl { span, bind, @@ -330,7 +325,7 @@ pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize { matcher .iter() .map(|tt| match tt { - TokenTree::MetaVarDecl(..) => 1, + TokenTree::MetaVarDecl { .. } => 1, TokenTree::Sequence(_, seq) => seq.num_captures, TokenTree::Delimited(.., delim) => count_metavar_decls(&delim.tts), TokenTree::Token(..) => 0, @@ -551,18 +546,12 @@ impl TtParser { mp.idx = idx_first; self.cur_mps.push(mp); } - &MatcherLoc::MetaVarDecl { span, kind, .. } => { + &MatcherLoc::MetaVarDecl { kind, .. } => { // Built-in nonterminals never start with these tokens, so we can eliminate // them from consideration. We use the span of the metavariable declaration // to determine any edition-specific matching behavior for non-terminals. - if let Some(kind) = kind { - if Parser::nonterminal_may_begin_with(kind, token) { - self.bb_mps.push(mp); - } - } else { - // E.g. `$e` instead of `$e:expr`, reported as a hard error if actually used. - // Both this check and the one in `nameize` are necessary, surprisingly. - return Some(Error(span, "missing fragment specifier".to_string())); + if Parser::nonterminal_may_begin_with(kind, token) { + self.bb_mps.push(mp); } } MatcherLoc::Eof => { @@ -666,11 +655,7 @@ impl TtParser { let mut mp = self.bb_mps.pop().unwrap(); let loc = &matcher[mp.idx]; if let &MatcherLoc::MetaVarDecl { - span, - kind: Some(kind), - next_metavar, - seq_depth, - .. + span, kind, next_metavar, seq_depth, .. } = loc { // We use the span of the metavariable declaration to determine any @@ -715,7 +700,7 @@ impl TtParser { .bb_mps .iter() .map(|mp| match &matcher[mp.idx] { - MatcherLoc::MetaVarDecl { bind, kind: Some(kind), .. } => { + MatcherLoc::MetaVarDecl { bind, kind, .. } => { format!("{kind} ('{bind}')") } _ => unreachable!(), @@ -745,19 +730,13 @@ impl TtParser { // `NamedParseResult`. Otherwise, it's an error. let mut ret_val = FxHashMap::default(); for loc in matcher { - if let &MatcherLoc::MetaVarDecl { span, bind, kind, .. } = loc { - if kind.is_some() { - match ret_val.entry(MacroRulesNormalizedIdent::new(bind)) { - Vacant(spot) => spot.insert(res.next().unwrap()), - Occupied(..) => { - return Error(span, format!("duplicated bind name: {bind}")); - } - }; - } else { - // E.g. `$e` instead of `$e:expr`, reported as a hard error if actually used. - // Both this check and the one in `parse_tt_inner` are necessary, surprisingly. - return Error(span, "missing fragment specifier".to_string()); - } + if let &MatcherLoc::MetaVarDecl { span, bind, .. } = loc { + match ret_val.entry(MacroRulesNormalizedIdent::new(bind)) { + Vacant(spot) => spot.insert(res.next().unwrap()), + Occupied(..) => { + return Error(span, format!("duplicated bind name: {bind}")); + } + }; } } Success(ret_val) diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 783f061ec6c5..432ab3247405 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -392,7 +392,7 @@ pub fn compile_declarative_macro( let lhs_nm = Ident::new(sym::lhs, span); let rhs_nm = Ident::new(sym::rhs, span); - let tt_spec = Some(NonterminalKind::TT); + let tt_spec = NonterminalKind::TT; let macro_rules = macro_def.macro_rules; // Parse the macro_rules! invocation @@ -407,9 +407,9 @@ pub fn compile_declarative_macro( DelimSpan::dummy(), mbe::SequenceRepetition { tts: vec![ - mbe::TokenTree::MetaVarDecl(span, lhs_nm, tt_spec), + mbe::TokenTree::MetaVarDecl { span, name: lhs_nm, kind: tt_spec }, mbe::TokenTree::token(token::FatArrow, span), - mbe::TokenTree::MetaVarDecl(span, rhs_nm, tt_spec), + mbe::TokenTree::MetaVarDecl { span, name: rhs_nm, kind: tt_spec }, ], separator: Some(Token::new( if macro_rules { token::Semi } else { token::Comma }, @@ -448,6 +448,7 @@ pub fn compile_declarative_macro( match tt_parser.parse_tt(&mut Cow::Owned(parser), &argument_gram, &mut NoopTracker) { Success(m) => m, Failure(()) => { + debug!("failed to parse macro tt"); // The fast `NoopTracker` doesn't have any info on failure, so we need to retry it // with another one that gives us the information we need. // For this we need to reclone the macro body as the previous parser consumed it. @@ -616,7 +617,7 @@ fn is_empty_token_tree(sess: &Session, seq: &mbe::SequenceRepetition) -> bool { let mut iter = seq.tts.iter().peekable(); while let Some(tt) = iter.next() { match tt { - mbe::TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Vis)) => {} + mbe::TokenTree::MetaVarDecl { kind: NonterminalKind::Vis, .. } => {} mbe::TokenTree::Token(t @ Token { kind: DocComment(..), .. }) => { let mut now = t; while let Some(&mbe::TokenTree::Token( @@ -651,7 +652,7 @@ fn check_redundant_vis_repetition( ) { let is_zero_or_one: bool = seq.kleene.op == KleeneOp::ZeroOrOne; let is_vis = seq.tts.first().map_or(false, |tt| { - matches!(tt, mbe::TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Vis))) + matches!(tt, mbe::TokenTree::MetaVarDecl { kind: NonterminalKind::Vis, .. }) }); if is_vis && is_zero_or_one { @@ -678,7 +679,7 @@ fn check_lhs_no_empty_seq(sess: &Session, tts: &[mbe::TokenTree]) -> Result<(), match tt { TokenTree::Token(..) | TokenTree::MetaVar(..) - | TokenTree::MetaVarDecl(..) + | TokenTree::MetaVarDecl { .. } | TokenTree::MetaVarExpr(..) => (), TokenTree::Delimited(.., del) => check_lhs_no_empty_seq(sess, &del.tts)?, TokenTree::Sequence(span, seq) => { @@ -777,7 +778,7 @@ impl<'tt> FirstSets<'tt> { match tt { TokenTree::Token(..) | TokenTree::MetaVar(..) - | TokenTree::MetaVarDecl(..) + | TokenTree::MetaVarDecl { .. } | TokenTree::MetaVarExpr(..) => { first.replace_with(TtHandle::TtRef(tt)); } @@ -845,7 +846,7 @@ impl<'tt> FirstSets<'tt> { match tt { TokenTree::Token(..) | TokenTree::MetaVar(..) - | TokenTree::MetaVarDecl(..) + | TokenTree::MetaVarDecl { .. } | TokenTree::MetaVarExpr(..) => { first.add_one(TtHandle::TtRef(tt)); return first; @@ -1084,7 +1085,7 @@ fn check_matcher_core<'tt>( match token { TokenTree::Token(..) | TokenTree::MetaVar(..) - | TokenTree::MetaVarDecl(..) + | TokenTree::MetaVarDecl { .. } | TokenTree::MetaVarExpr(..) => { if token_can_be_followed_by_any(token) { // don't need to track tokens that work with any, @@ -1152,7 +1153,7 @@ fn check_matcher_core<'tt>( // Now `last` holds the complete set of NT tokens that could // end the sequence before SUFFIX. Check that every one works with `suffix`. for tt in &last.tokens { - if let &TokenTree::MetaVarDecl(span, name, Some(kind)) = tt.get() { + if let &TokenTree::MetaVarDecl { span, name, kind } = tt.get() { for next_token in &suffix_first.tokens { let next_token = next_token.get(); @@ -1172,11 +1173,11 @@ fn check_matcher_core<'tt>( ) { // It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param. - let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( + let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl { span, name, - Some(NonterminalKind::Pat(PatParam { inferred: false })), - )); + kind: NonterminalKind::Pat(PatParam { inferred: false }), + }); sess.psess.buffer_lint( RUST_2021_INCOMPATIBLE_OR_PATTERNS, span, @@ -1212,11 +1213,11 @@ fn check_matcher_core<'tt>( && sess.psess.edition.at_least_rust_2021() && next_token.is_token(&token::Or) { - let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( + let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl { span, name, - Some(NonterminalKind::Pat(PatParam { inferred: false })), - )); + kind: NonterminalKind::Pat(PatParam { inferred: false }), + }); err.span_suggestion( span, "try a `pat_param` fragment specifier instead", @@ -1254,7 +1255,7 @@ fn check_matcher_core<'tt>( } fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool { - if let mbe::TokenTree::MetaVarDecl(_, _, Some(kind)) = *tok { + if let mbe::TokenTree::MetaVarDecl { kind, .. } = *tok { frag_can_be_followed_by_any(kind) } else { // (Non NT's can always be followed by anything in matchers.) @@ -1367,7 +1368,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { } _ => IsInFollow::No(TOKENS), }, - TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Block)) => IsInFollow::Yes, + TokenTree::MetaVarDecl { kind: NonterminalKind::Block, .. } => IsInFollow::Yes, _ => IsInFollow::No(TOKENS), } } @@ -1400,11 +1401,10 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { } } }, - TokenTree::MetaVarDecl( - _, - _, - Some(NonterminalKind::Ident | NonterminalKind::Ty | NonterminalKind::Path), - ) => IsInFollow::Yes, + TokenTree::MetaVarDecl { + kind: NonterminalKind::Ident | NonterminalKind::Ty | NonterminalKind::Path, + .. + } => IsInFollow::Yes, _ => IsInFollow::No(TOKENS), } } @@ -1416,8 +1416,7 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { match tt { mbe::TokenTree::Token(token) => pprust::token_to_string(token).into(), mbe::TokenTree::MetaVar(_, name) => format!("${name}"), - mbe::TokenTree::MetaVarDecl(_, name, Some(kind)) => format!("${name}:{kind}"), - mbe::TokenTree::MetaVarDecl(_, name, None) => format!("${name}:"), + mbe::TokenTree::MetaVarDecl { name, kind, .. } => format!("${name}:{kind}"), _ => panic!( "{}", "unexpected mbe::TokenTree::{Sequence or Delimited} \ diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 0c2362f23bcf..2daa4e715584 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -54,66 +54,78 @@ pub(super) fn parse( // Given the parsed tree, if there is a metavar and we are expecting matchers, actually // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`). let tree = parse_tree(tree, &mut iter, parsing_patterns, sess, node_id, features, edition); - match tree { - TokenTree::MetaVar(start_sp, ident) if parsing_patterns => { - // Not consuming the next token immediately, as it may not be a colon - let span = match iter.peek() { - Some(&tokenstream::TokenTree::Token( - Token { kind: token::Colon, span: colon_span }, - _, - )) => { - // Consume the colon first - iter.next(); - // It's ok to consume the next tree no matter how, - // since if it's not a token then it will be an invalid declaration. - match iter.next() { - Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() { - Some((fragment, _)) => { - let span = token.span.with_lo(start_sp.lo()); - let edition = || { - // FIXME(#85708) - once we properly decode a foreign - // crate's `SyntaxContext::root`, then we can replace - // this with just `span.edition()`. A - // `SyntaxContext::root()` from the current crate will - // have the edition of the current crate, and a - // `SyntaxContext::root()` from a foreign crate will - // have the edition of that crate (which we manually - // retrieve via the `edition` parameter). - if !span.from_expansion() { - edition - } else { - span.edition() - } - }; - let kind = NonterminalKind::from_symbol(fragment.name, edition) - .unwrap_or_else(|| { - sess.dcx().emit_err(errors::InvalidFragmentSpecifier { - span, - fragment, - help: VALID_FRAGMENT_NAMES_MSG.into(), - }); - NonterminalKind::Ident - }); - result.push(TokenTree::MetaVarDecl(span, ident, Some(kind))); - continue; - } - _ => token.span, - }, - // Invalid, return a nice source location - _ => colon_span.with_lo(start_sp.lo()), - } - } - // Whether it's none or some other tree, it doesn't belong to - // the current meta variable, returning the original span. - _ => start_sp, - }; + if !parsing_patterns { + // No matchers allowed, nothing to process here + result.push(tree); + continue; + } - result.push(TokenTree::MetaVarDecl(span, ident, None)); - } + let TokenTree::MetaVar(start_sp, ident) = tree else { + // Not a metavariable, just return the tree + result.push(tree); + continue; + }; - // Not a metavar or no matchers allowed, so just return the tree - _ => result.push(tree), + // Push a metavariable with no fragment specifier at the given span + let mut missing_fragment_specifier = |span| { + sess.dcx().emit_err(errors::MissingFragmentSpecifier { + span, + add_span: span.shrink_to_hi(), + valid: VALID_FRAGMENT_NAMES_MSG, + }); + + // Fall back to a `TokenTree` since that will match anything if we continue expanding. + result.push(TokenTree::MetaVarDecl { span, name: ident, kind: NonterminalKind::TT }); + }; + + // Not consuming the next token immediately, as it may not be a colon + if let Some(peek) = iter.peek() + && let tokenstream::TokenTree::Token(token, _spacing) = peek + && let Token { kind: token::Colon, span: colon_span } = token + { + // Next token is a colon; consume it + iter.next(); + + // It's ok to consume the next tree no matter how, + // since if it's not a token then it will be an invalid declaration. + let Some(tokenstream::TokenTree::Token(token, _)) = iter.next() else { + // Invalid, return a nice source location as `var:` + missing_fragment_specifier(colon_span.with_lo(start_sp.lo())); + continue; + }; + + let Some((fragment, _)) = token.ident() else { + // No identifier for the fragment specifier; + missing_fragment_specifier(token.span); + continue; + }; + + let span = token.span.with_lo(start_sp.lo()); + let edition = || { + // FIXME(#85708) - once we properly decode a foreign + // crate's `SyntaxContext::root`, then we can replace + // this with just `span.edition()`. A + // `SyntaxContext::root()` from the current crate will + // have the edition of the current crate, and a + // `SyntaxContext::root()` from a foreign crate will + // have the edition of that crate (which we manually + // retrieve via the `edition` parameter). + if !span.from_expansion() { edition } else { span.edition() } + }; + let kind = NonterminalKind::from_symbol(fragment.name, edition).unwrap_or_else(|| { + sess.dcx().emit_err(errors::InvalidFragmentSpecifier { + span, + fragment, + help: VALID_FRAGMENT_NAMES_MSG, + }); + NonterminalKind::TT + }); + result.push(TokenTree::MetaVarDecl { span, name: ident, kind }); + } else { + // Whether it's none or some other tree, it doesn't belong to + // the current meta variable, returning the original span. + missing_fragment_specifier(start_sp); } } result diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 2d3fd7702da5..a8c4a9e4b1b4 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -9,7 +9,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize}; use rustc_parse::lexer::nfc_normalize; use rustc_parse::parser::ParseNtResult; -use rustc_session::parse::{ParseSess, SymbolGallery}; +use rustc_session::parse::ParseSess; use rustc_span::hygiene::{LocalExpnId, Transparency}; use rustc_span::{ Ident, MacroRulesNormalizedIdent, Span, Symbol, SyntaxContext, sym, with_metavar_spans, @@ -25,20 +25,77 @@ use crate::mbe::macro_parser::NamedMatch::*; use crate::mbe::metavar_expr::{MetaVarExprConcatElem, RAW_IDENT_ERR}; use crate::mbe::{self, KleeneOp, MetaVarExpr}; -// A Marker adds the given mark to the syntax context. -struct Marker(LocalExpnId, Transparency, FxHashMap); +/// Context needed to perform transcription of metavariable expressions. +struct TranscrCtx<'psess, 'itp> { + psess: &'psess ParseSess, + + /// Map from metavars to matched tokens + interp: &'itp FxHashMap, + + /// Allow marking spans. + marker: Marker, + + /// The stack of things yet to be completely expanded. + /// + /// We descend into the RHS (`src`), expanding things as we go. This stack contains the things + /// we have yet to expand/are still expanding. We start the stack off with the whole RHS. The + /// choice of spacing values doesn't matter. + stack: SmallVec<[Frame<'itp>; 1]>, + + /// A stack of where we are in the repeat expansion. + /// + /// As we descend in the RHS, we will need to be able to match nested sequences of matchers. + /// `repeats` keeps track of where we are in matching at each level, with the last element + /// being the most deeply nested sequence. This is used as a stack. + repeats: Vec<(usize, usize)>, + + /// The resulting token stream from the `TokenTree` we just finished processing. + /// + /// At the end, this will contain the full result of transcription, but at arbitrary points + /// during `transcribe`, `result` will contain subsets of the final result. + /// + /// Specifically, as we descend into each TokenTree, we will push the existing results onto the + /// `result_stack` and clear `results`. We will then produce the results of transcribing the + /// TokenTree into `results`. Then, as we unwind back out of the `TokenTree`, we will pop the + /// `result_stack` and append `results` too it to produce the new `results` up to that point. + /// + /// Thus, if we try to pop the `result_stack` and it is empty, we have reached the top-level + /// again, and we are done transcribing. + result: Vec, + + /// The in-progress `result` lives at the top of this stack. Each entered `TokenTree` adds a + /// new entry. + result_stack: Vec>, +} + +impl<'psess> TranscrCtx<'psess, '_> { + /// Span marked with the correct expansion and transparency. + fn visited_dspan(&mut self, dspan: DelimSpan) -> Span { + let mut span = dspan.entire(); + self.marker.mark_span(&mut span); + span + } +} + +/// A Marker adds the given mark to the syntax context. +struct Marker { + expand_id: LocalExpnId, + transparency: Transparency, + cache: FxHashMap, +} impl Marker { + /// Mark a span with the stored expansion ID and transparency. fn mark_span(&mut self, span: &mut Span) { // `apply_mark` is a relatively expensive operation, both due to taking hygiene lock, and // by itself. All tokens in a macro body typically have the same syntactic context, unless // it's some advanced case with macro-generated macros. So if we cache the marked version // of that context once, we'll typically have a 100% cache hit rate after that. - let Marker(expn_id, transparency, ref mut cache) = *self; *span = span.map_ctxt(|ctxt| { - *cache + *self + .cache .entry(ctxt) - .or_insert_with(|| ctxt.apply_mark(expn_id.to_expn_id(), transparency)) + .or_insert_with(|| ctxt.apply_mark(self.expand_id.to_expn_id(), self.transparency)) }); } } @@ -116,52 +173,36 @@ pub(super) fn transcribe<'a>( return Ok(TokenStream::default()); } - // We descend into the RHS (`src`), expanding things as we go. This stack contains the things - // we have yet to expand/are still expanding. We start the stack off with the whole RHS. The - // choice of spacing values doesn't matter. - let mut stack: SmallVec<[Frame<'_>; 1]> = smallvec![Frame::new_delimited( - src, - src_span, - DelimSpacing::new(Spacing::Alone, Spacing::Alone) - )]; + let mut tscx = TranscrCtx { + psess, + interp, + marker: Marker { expand_id, transparency, cache: Default::default() }, + repeats: Vec::new(), + stack: smallvec![Frame::new_delimited( + src, + src_span, + DelimSpacing::new(Spacing::Alone, Spacing::Alone) + )], + result: Vec::new(), + result_stack: Vec::new(), + }; - // As we descend in the RHS, we will need to be able to match nested sequences of matchers. - // `repeats` keeps track of where we are in matching at each level, with the last element being - // the most deeply nested sequence. This is used as a stack. - let mut repeats: Vec<(usize, usize)> = Vec::new(); - - // `result` contains resulting token stream from the TokenTree we just finished processing. At - // the end, this will contain the full result of transcription, but at arbitrary points during - // `transcribe`, `result` will contain subsets of the final result. - // - // Specifically, as we descend into each TokenTree, we will push the existing results onto the - // `result_stack` and clear `results`. We will then produce the results of transcribing the - // TokenTree into `results`. Then, as we unwind back out of the `TokenTree`, we will pop the - // `result_stack` and append `results` too it to produce the new `results` up to that point. - // - // Thus, if we try to pop the `result_stack` and it is empty, we have reached the top-level - // again, and we are done transcribing. - let mut result: Vec = Vec::new(); - let mut result_stack = Vec::new(); - let mut marker = Marker(expand_id, transparency, Default::default()); - - let dcx = psess.dcx(); loop { // Look at the last frame on the stack. // If it still has a TokenTree we have not looked at yet, use that tree. - let Some(tree) = stack.last_mut().unwrap().next() else { + let Some(tree) = tscx.stack.last_mut().unwrap().next() else { // This else-case never produces a value for `tree` (it `continue`s or `return`s). // Otherwise, if we have just reached the end of a sequence and we can keep repeating, // go back to the beginning of the sequence. - let frame = stack.last_mut().unwrap(); + let frame = tscx.stack.last_mut().unwrap(); if let FrameKind::Sequence { sep, .. } = &frame.kind { - let (repeat_idx, repeat_len) = repeats.last_mut().unwrap(); + let (repeat_idx, repeat_len) = tscx.repeats.last_mut().unwrap(); *repeat_idx += 1; if repeat_idx < repeat_len { frame.idx = 0; if let Some(sep) = sep { - result.push(TokenTree::Token(*sep, Spacing::Alone)); + tscx.result.push(TokenTree::Token(*sep, Spacing::Alone)); } continue; } @@ -170,10 +211,10 @@ pub(super) fn transcribe<'a>( // We are done with the top of the stack. Pop it. Depending on what it was, we do // different things. Note that the outermost item must be the delimited, wrapped RHS // that was passed in originally to `transcribe`. - match stack.pop().unwrap().kind { + match tscx.stack.pop().unwrap().kind { // Done with a sequence. Pop from repeats. FrameKind::Sequence { .. } => { - repeats.pop(); + tscx.repeats.pop(); } // We are done processing a Delimited. If this is the top-level delimited, we are @@ -185,15 +226,16 @@ pub(super) fn transcribe<'a>( if delim == Delimiter::Bracket { spacing.close = Spacing::Alone; } - if result_stack.is_empty() { + if tscx.result_stack.is_empty() { // No results left to compute! We are back at the top-level. - return Ok(TokenStream::new(result)); + return Ok(TokenStream::new(tscx.result)); } // Step back into the parent Delimited. - let tree = TokenTree::Delimited(span, spacing, delim, TokenStream::new(result)); - result = result_stack.pop().unwrap(); - result.push(tree); + let tree = + TokenTree::Delimited(span, spacing, delim, TokenStream::new(tscx.result)); + tscx.result = tscx.result_stack.pop().unwrap(); + tscx.result.push(tree); } } continue; @@ -202,223 +244,19 @@ pub(super) fn transcribe<'a>( // At this point, we know we are in the middle of a TokenTree (the last one on `stack`). // `tree` contains the next `TokenTree` to be processed. match tree { - // We are descending into a sequence. We first make sure that the matchers in the RHS - // and the matches in `interp` have the same shape. Otherwise, either the caller or the - // macro writer has made a mistake. + // Replace the sequence with its expansion. seq @ mbe::TokenTree::Sequence(_, seq_rep) => { - match lockstep_iter_size(seq, interp, &repeats) { - LockstepIterSize::Unconstrained => { - return Err(dcx.create_err(NoSyntaxVarsExprRepeat { span: seq.span() })); - } - - LockstepIterSize::Contradiction(msg) => { - // FIXME: this really ought to be caught at macro definition time... It - // happens when two meta-variables are used in the same repetition in a - // sequence, but they come from different sequence matchers and repeat - // different amounts. - return Err( - dcx.create_err(MetaVarsDifSeqMatchers { span: seq.span(), msg }) - ); - } - - LockstepIterSize::Constraint(len, _) => { - // We do this to avoid an extra clone above. We know that this is a - // sequence already. - let mbe::TokenTree::Sequence(sp, seq) = seq else { unreachable!() }; - - // Is the repetition empty? - if len == 0 { - if seq.kleene.op == KleeneOp::OneOrMore { - // FIXME: this really ought to be caught at macro definition - // time... It happens when the Kleene operator in the matcher and - // the body for the same meta-variable do not match. - return Err(dcx.create_err(MustRepeatOnce { span: sp.entire() })); - } - } else { - // 0 is the initial counter (we have done 0 repetitions so far). `len` - // is the total number of repetitions we should generate. - repeats.push((0, len)); - - // The first time we encounter the sequence we push it to the stack. It - // then gets reused (see the beginning of the loop) until we are done - // repeating. - stack.push(Frame::new_sequence( - seq_rep, - seq.separator.clone(), - seq.kleene.op, - )); - } - } - } + transcribe_sequence(&mut tscx, seq, seq_rep)?; } // Replace the meta-var with the matched token tree from the invocation. - &mbe::TokenTree::MetaVar(mut sp, mut original_ident) => { - // Find the matched nonterminal from the macro invocation, and use it to replace - // the meta-var. - // - // We use `Spacing::Alone` everywhere here, because that's the conservative choice - // and spacing of declarative macros is tricky. E.g. in this macro: - // ``` - // macro_rules! idents { - // ($($a:ident,)*) => { stringify!($($a)*) } - // } - // ``` - // `$a` has no whitespace after it and will be marked `JointHidden`. If you then - // call `idents!(x,y,z,)`, each of `x`, `y`, and `z` will be marked as `Joint`. So - // if you choose to use `$x`'s spacing or the identifier's spacing, you'll end up - // producing "xyz", which is bad because it effectively merges tokens. - // `Spacing::Alone` is the safer option. Fortunately, `space_between` will avoid - // some of the unnecessary whitespace. - let ident = MacroRulesNormalizedIdent::new(original_ident); - if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { - // We wrap the tokens in invisible delimiters, unless they are already wrapped - // in invisible delimiters with the same `MetaVarKind`. Because some proc - // macros can't handle multiple layers of invisible delimiters of the same - // `MetaVarKind`. This loses some span info, though it hopefully won't matter. - let mut mk_delimited = |mk_span, mv_kind, mut stream: TokenStream| { - if stream.len() == 1 { - let tree = stream.iter().next().unwrap(); - if let TokenTree::Delimited(_, _, delim, inner) = tree - && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mvk)) = delim - && mv_kind == *mvk - { - stream = inner.clone(); - } - } - - // Emit as a token stream within `Delimiter::Invisible` to maintain - // parsing priorities. - marker.mark_span(&mut sp); - with_metavar_spans(|mspans| mspans.insert(mk_span, sp)); - // Both the open delim and close delim get the same span, which covers the - // `$foo` in the decl macro RHS. - TokenTree::Delimited( - DelimSpan::from_single(sp), - DelimSpacing::new(Spacing::Alone, Spacing::Alone), - Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)), - stream, - ) - }; - let tt = match cur_matched { - MatchedSingle(ParseNtResult::Tt(tt)) => { - // `tt`s are emitted into the output stream directly as "raw tokens", - // without wrapping them into groups. Other variables are emitted into - // the output stream as groups with `Delimiter::Invisible` to maintain - // parsing priorities. - maybe_use_metavar_location(psess, &stack, sp, tt, &mut marker) - } - MatchedSingle(ParseNtResult::Ident(ident, is_raw)) => { - marker.mark_span(&mut sp); - with_metavar_spans(|mspans| mspans.insert(ident.span, sp)); - let kind = token::NtIdent(*ident, *is_raw); - TokenTree::token_alone(kind, sp) - } - MatchedSingle(ParseNtResult::Lifetime(ident, is_raw)) => { - marker.mark_span(&mut sp); - with_metavar_spans(|mspans| mspans.insert(ident.span, sp)); - let kind = token::NtLifetime(*ident, *is_raw); - TokenTree::token_alone(kind, sp) - } - MatchedSingle(ParseNtResult::Item(item)) => { - mk_delimited(item.span, MetaVarKind::Item, TokenStream::from_ast(item)) - } - MatchedSingle(ParseNtResult::Block(block)) => mk_delimited( - block.span, - MetaVarKind::Block, - TokenStream::from_ast(block), - ), - MatchedSingle(ParseNtResult::Stmt(stmt)) => { - let stream = if let StmtKind::Empty = stmt.kind { - // FIXME: Properly collect tokens for empty statements. - TokenStream::token_alone(token::Semi, stmt.span) - } else { - TokenStream::from_ast(stmt) - }; - mk_delimited(stmt.span, MetaVarKind::Stmt, stream) - } - MatchedSingle(ParseNtResult::Pat(pat, pat_kind)) => mk_delimited( - pat.span, - MetaVarKind::Pat(*pat_kind), - TokenStream::from_ast(pat), - ), - MatchedSingle(ParseNtResult::Expr(expr, kind)) => { - let (can_begin_literal_maybe_minus, can_begin_string_literal) = - match &expr.kind { - ExprKind::Lit(_) => (true, true), - ExprKind::Unary(UnOp::Neg, e) - if matches!(&e.kind, ExprKind::Lit(_)) => - { - (true, false) - } - _ => (false, false), - }; - mk_delimited( - expr.span, - MetaVarKind::Expr { - kind: *kind, - can_begin_literal_maybe_minus, - can_begin_string_literal, - }, - TokenStream::from_ast(expr), - ) - } - MatchedSingle(ParseNtResult::Literal(lit)) => { - mk_delimited(lit.span, MetaVarKind::Literal, TokenStream::from_ast(lit)) - } - MatchedSingle(ParseNtResult::Ty(ty)) => { - let is_path = matches!(&ty.kind, TyKind::Path(None, _path)); - mk_delimited( - ty.span, - MetaVarKind::Ty { is_path }, - TokenStream::from_ast(ty), - ) - } - MatchedSingle(ParseNtResult::Meta(attr_item)) => { - let has_meta_form = attr_item.meta_kind().is_some(); - mk_delimited( - attr_item.span(), - MetaVarKind::Meta { has_meta_form }, - TokenStream::from_ast(attr_item), - ) - } - MatchedSingle(ParseNtResult::Path(path)) => { - mk_delimited(path.span, MetaVarKind::Path, TokenStream::from_ast(path)) - } - MatchedSingle(ParseNtResult::Vis(vis)) => { - mk_delimited(vis.span, MetaVarKind::Vis, TokenStream::from_ast(vis)) - } - MatchedSeq(..) => { - // We were unable to descend far enough. This is an error. - return Err(dcx.create_err(VarStillRepeating { span: sp, ident })); - } - }; - result.push(tt) - } else { - // If we aren't able to match the meta-var, we push it back into the result but - // with modified syntax context. (I believe this supports nested macros). - marker.mark_span(&mut sp); - marker.mark_span(&mut original_ident.span); - result.push(TokenTree::token_joint_hidden(token::Dollar, sp)); - result.push(TokenTree::Token( - Token::from_ast_ident(original_ident), - Spacing::Alone, - )); - } + &mbe::TokenTree::MetaVar(sp, original_ident) => { + transcribe_metavar(&mut tscx, sp, original_ident)?; } // Replace meta-variable expressions with the result of their expansion. - mbe::TokenTree::MetaVarExpr(sp, expr) => { - transcribe_metavar_expr( - dcx, - expr, - interp, - &mut marker, - &repeats, - &mut result, - sp, - &psess.symbol_gallery, - )?; + mbe::TokenTree::MetaVarExpr(dspan, expr) => { + transcribe_metavar_expr(&mut tscx, *dspan, expr)?; } // If we are entering a new delimiter, we push its contents to the `stack` to be @@ -427,29 +265,328 @@ pub(super) fn transcribe<'a>( // jump back out of the Delimited, pop the result_stack and add the new results back to // the previous results (from outside the Delimited). &mbe::TokenTree::Delimited(mut span, ref spacing, ref delimited) => { - marker.mark_span(&mut span.open); - marker.mark_span(&mut span.close); - stack.push(Frame::new_delimited(delimited, span, *spacing)); - result_stack.push(mem::take(&mut result)); + tscx.marker.mark_span(&mut span.open); + tscx.marker.mark_span(&mut span.close); + tscx.stack.push(Frame::new_delimited(delimited, span, *spacing)); + tscx.result_stack.push(mem::take(&mut tscx.result)); } // Nothing much to do here. Just push the token to the result, being careful to // preserve syntax context. &mbe::TokenTree::Token(mut token) => { - marker.mark_span(&mut token.span); + tscx.marker.mark_span(&mut token.span); if let token::NtIdent(ident, _) | token::NtLifetime(ident, _) = &mut token.kind { - marker.mark_span(&mut ident.span); + tscx.marker.mark_span(&mut ident.span); } let tt = TokenTree::Token(token, Spacing::Alone); - result.push(tt); + tscx.result.push(tt); } // There should be no meta-var declarations in the invocation of a macro. - mbe::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl`"), + mbe::TokenTree::MetaVarDecl { .. } => panic!("unexpected `TokenTree::MetaVarDecl`"), } } } +/// Turn `$(...)*` sequences into tokens. +fn transcribe_sequence<'tx, 'itp>( + tscx: &mut TranscrCtx<'tx, 'itp>, + seq: &mbe::TokenTree, + seq_rep: &'itp mbe::SequenceRepetition, +) -> PResult<'tx, ()> { + let dcx = tscx.psess.dcx(); + + // We are descending into a sequence. We first make sure that the matchers in the RHS + // and the matches in `interp` have the same shape. Otherwise, either the caller or the + // macro writer has made a mistake. + match lockstep_iter_size(seq, tscx.interp, &tscx.repeats) { + LockstepIterSize::Unconstrained => { + return Err(dcx.create_err(NoSyntaxVarsExprRepeat { span: seq.span() })); + } + + LockstepIterSize::Contradiction(msg) => { + // FIXME: this really ought to be caught at macro definition time... It + // happens when two meta-variables are used in the same repetition in a + // sequence, but they come from different sequence matchers and repeat + // different amounts. + return Err(dcx.create_err(MetaVarsDifSeqMatchers { span: seq.span(), msg })); + } + + LockstepIterSize::Constraint(len, _) => { + // We do this to avoid an extra clone above. We know that this is a + // sequence already. + let mbe::TokenTree::Sequence(sp, seq) = seq else { unreachable!() }; + + // Is the repetition empty? + if len == 0 { + if seq.kleene.op == KleeneOp::OneOrMore { + // FIXME: this really ought to be caught at macro definition + // time... It happens when the Kleene operator in the matcher and + // the body for the same meta-variable do not match. + return Err(dcx.create_err(MustRepeatOnce { span: sp.entire() })); + } + } else { + // 0 is the initial counter (we have done 0 repetitions so far). `len` + // is the total number of repetitions we should generate. + tscx.repeats.push((0, len)); + + // The first time we encounter the sequence we push it to the stack. It + // then gets reused (see the beginning of the loop) until we are done + // repeating. + tscx.stack.push(Frame::new_sequence(seq_rep, seq.separator.clone(), seq.kleene.op)); + } + } + } + + Ok(()) +} + +/// Find the matched nonterminal from the macro invocation, and use it to replace +/// the meta-var. +/// +/// We use `Spacing::Alone` everywhere here, because that's the conservative choice +/// and spacing of declarative macros is tricky. E.g. in this macro: +/// ``` +/// macro_rules! idents { +/// ($($a:ident,)*) => { stringify!($($a)*) } +/// } +/// ``` +/// `$a` has no whitespace after it and will be marked `JointHidden`. If you then +/// call `idents!(x,y,z,)`, each of `x`, `y`, and `z` will be marked as `Joint`. So +/// if you choose to use `$x`'s spacing or the identifier's spacing, you'll end up +/// producing "xyz", which is bad because it effectively merges tokens. +/// `Spacing::Alone` is the safer option. Fortunately, `space_between` will avoid +/// some of the unnecessary whitespace. +fn transcribe_metavar<'tx>( + tscx: &mut TranscrCtx<'tx, '_>, + mut sp: Span, + mut original_ident: Ident, +) -> PResult<'tx, ()> { + let dcx = tscx.psess.dcx(); + + let ident = MacroRulesNormalizedIdent::new(original_ident); + let Some(cur_matched) = lookup_cur_matched(ident, tscx.interp, &tscx.repeats) else { + // If we aren't able to match the meta-var, we push it back into the result but + // with modified syntax context. (I believe this supports nested macros). + tscx.marker.mark_span(&mut sp); + tscx.marker.mark_span(&mut original_ident.span); + tscx.result.push(TokenTree::token_joint_hidden(token::Dollar, sp)); + tscx.result.push(TokenTree::Token(Token::from_ast_ident(original_ident), Spacing::Alone)); + return Ok(()); + }; + + // We wrap the tokens in invisible delimiters, unless they are already wrapped + // in invisible delimiters with the same `MetaVarKind`. Because some proc + // macros can't handle multiple layers of invisible delimiters of the same + // `MetaVarKind`. This loses some span info, though it hopefully won't matter. + let mut mk_delimited = |mk_span, mv_kind, mut stream: TokenStream| { + if stream.len() == 1 { + let tree = stream.iter().next().unwrap(); + if let TokenTree::Delimited(_, _, delim, inner) = tree + && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mvk)) = delim + && mv_kind == *mvk + { + stream = inner.clone(); + } + } + + // Emit as a token stream within `Delimiter::Invisible` to maintain + // parsing priorities. + tscx.marker.mark_span(&mut sp); + with_metavar_spans(|mspans| mspans.insert(mk_span, sp)); + // Both the open delim and close delim get the same span, which covers the + // `$foo` in the decl macro RHS. + TokenTree::Delimited( + DelimSpan::from_single(sp), + DelimSpacing::new(Spacing::Alone, Spacing::Alone), + Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)), + stream, + ) + }; + + let tt = match cur_matched { + MatchedSingle(ParseNtResult::Tt(tt)) => { + // `tt`s are emitted into the output stream directly as "raw tokens", + // without wrapping them into groups. Other variables are emitted into + // the output stream as groups with `Delimiter::Invisible` to maintain + // parsing priorities. + maybe_use_metavar_location(tscx.psess, &tscx.stack, sp, tt, &mut tscx.marker) + } + MatchedSingle(ParseNtResult::Ident(ident, is_raw)) => { + tscx.marker.mark_span(&mut sp); + with_metavar_spans(|mspans| mspans.insert(ident.span, sp)); + let kind = token::NtIdent(*ident, *is_raw); + TokenTree::token_alone(kind, sp) + } + MatchedSingle(ParseNtResult::Lifetime(ident, is_raw)) => { + tscx.marker.mark_span(&mut sp); + with_metavar_spans(|mspans| mspans.insert(ident.span, sp)); + let kind = token::NtLifetime(*ident, *is_raw); + TokenTree::token_alone(kind, sp) + } + MatchedSingle(ParseNtResult::Item(item)) => { + mk_delimited(item.span, MetaVarKind::Item, TokenStream::from_ast(item)) + } + MatchedSingle(ParseNtResult::Block(block)) => { + mk_delimited(block.span, MetaVarKind::Block, TokenStream::from_ast(block)) + } + MatchedSingle(ParseNtResult::Stmt(stmt)) => { + let stream = if let StmtKind::Empty = stmt.kind { + // FIXME: Properly collect tokens for empty statements. + TokenStream::token_alone(token::Semi, stmt.span) + } else { + TokenStream::from_ast(stmt) + }; + mk_delimited(stmt.span, MetaVarKind::Stmt, stream) + } + MatchedSingle(ParseNtResult::Pat(pat, pat_kind)) => { + mk_delimited(pat.span, MetaVarKind::Pat(*pat_kind), TokenStream::from_ast(pat)) + } + MatchedSingle(ParseNtResult::Expr(expr, kind)) => { + let (can_begin_literal_maybe_minus, can_begin_string_literal) = match &expr.kind { + ExprKind::Lit(_) => (true, true), + ExprKind::Unary(UnOp::Neg, e) if matches!(&e.kind, ExprKind::Lit(_)) => { + (true, false) + } + _ => (false, false), + }; + mk_delimited( + expr.span, + MetaVarKind::Expr { + kind: *kind, + can_begin_literal_maybe_minus, + can_begin_string_literal, + }, + TokenStream::from_ast(expr), + ) + } + MatchedSingle(ParseNtResult::Literal(lit)) => { + mk_delimited(lit.span, MetaVarKind::Literal, TokenStream::from_ast(lit)) + } + MatchedSingle(ParseNtResult::Ty(ty)) => { + let is_path = matches!(&ty.kind, TyKind::Path(None, _path)); + mk_delimited(ty.span, MetaVarKind::Ty { is_path }, TokenStream::from_ast(ty)) + } + MatchedSingle(ParseNtResult::Meta(attr_item)) => { + let has_meta_form = attr_item.meta_kind().is_some(); + mk_delimited( + attr_item.span(), + MetaVarKind::Meta { has_meta_form }, + TokenStream::from_ast(attr_item), + ) + } + MatchedSingle(ParseNtResult::Path(path)) => { + mk_delimited(path.span, MetaVarKind::Path, TokenStream::from_ast(path)) + } + MatchedSingle(ParseNtResult::Vis(vis)) => { + mk_delimited(vis.span, MetaVarKind::Vis, TokenStream::from_ast(vis)) + } + MatchedSeq(..) => { + // We were unable to descend far enough. This is an error. + return Err(dcx.create_err(VarStillRepeating { span: sp, ident })); + } + }; + + tscx.result.push(tt); + Ok(()) +} + +/// Turn `${expr(...)}` metavariable expressionss into tokens. +fn transcribe_metavar_expr<'tx>( + tscx: &mut TranscrCtx<'tx, '_>, + dspan: DelimSpan, + expr: &MetaVarExpr, +) -> PResult<'tx, ()> { + let dcx = tscx.psess.dcx(); + let tt = match *expr { + MetaVarExpr::Concat(ref elements) => metavar_expr_concat(tscx, dspan, elements)?, + MetaVarExpr::Count(original_ident, depth) => { + let matched = matched_from_ident(dcx, original_ident, tscx.interp)?; + let count = count_repetitions(dcx, depth, matched, &tscx.repeats, &dspan)?; + TokenTree::token_alone( + TokenKind::lit(token::Integer, sym::integer(count), None), + tscx.visited_dspan(dspan), + ) + } + MetaVarExpr::Ignore(original_ident) => { + // Used to ensure that `original_ident` is present in the LHS + let _ = matched_from_ident(dcx, original_ident, tscx.interp)?; + return Ok(()); + } + MetaVarExpr::Index(depth) => match tscx.repeats.iter().nth_back(depth) { + Some((index, _)) => TokenTree::token_alone( + TokenKind::lit(token::Integer, sym::integer(*index), None), + tscx.visited_dspan(dspan), + ), + None => { + return Err(out_of_bounds_err(dcx, tscx.repeats.len(), dspan.entire(), "index")); + } + }, + MetaVarExpr::Len(depth) => match tscx.repeats.iter().nth_back(depth) { + Some((_, length)) => TokenTree::token_alone( + TokenKind::lit(token::Integer, sym::integer(*length), None), + tscx.visited_dspan(dspan), + ), + None => { + return Err(out_of_bounds_err(dcx, tscx.repeats.len(), dspan.entire(), "len")); + } + }, + }; + tscx.result.push(tt); + Ok(()) +} + +/// Handle the `${concat(...)}` metavariable expression. +fn metavar_expr_concat<'tx>( + tscx: &mut TranscrCtx<'tx, '_>, + dspan: DelimSpan, + elements: &[MetaVarExprConcatElem], +) -> PResult<'tx, TokenTree> { + let dcx = tscx.psess.dcx(); + let mut concatenated = String::new(); + for element in elements.into_iter() { + let symbol = match element { + MetaVarExprConcatElem::Ident(elem) => elem.name, + MetaVarExprConcatElem::Literal(elem) => *elem, + MetaVarExprConcatElem::Var(ident) => { + match matched_from_ident(dcx, *ident, tscx.interp)? { + NamedMatch::MatchedSeq(named_matches) => { + let Some((curr_idx, _)) = tscx.repeats.last() else { + return Err(dcx.struct_span_err(dspan.entire(), "invalid syntax")); + }; + match &named_matches[*curr_idx] { + // FIXME(c410-f3r) Nested repetitions are unimplemented + MatchedSeq(_) => unimplemented!(), + MatchedSingle(pnr) => extract_symbol_from_pnr(dcx, pnr, ident.span)?, + } + } + NamedMatch::MatchedSingle(pnr) => { + extract_symbol_from_pnr(dcx, pnr, ident.span)? + } + } + } + }; + concatenated.push_str(symbol.as_str()); + } + let symbol = nfc_normalize(&concatenated); + let concatenated_span = tscx.visited_dspan(dspan); + if !rustc_lexer::is_ident(symbol.as_str()) { + return Err(dcx.struct_span_err( + concatenated_span, + "`${concat(..)}` is not generating a valid identifier", + )); + } + tscx.psess.symbol_gallery.insert(symbol, concatenated_span); + + // The current implementation marks the span as coming from the macro regardless of + // contexts of the concatenated identifiers but this behavior may change in the + // future. + Ok(TokenTree::Token( + Token::from_ast_ident(Ident::new(symbol, concatenated_span)), + Spacing::Alone, + )) +} + /// Store the metavariable span for this original span into a side table. /// FIXME: Try to put the metavariable span into `SpanData` instead of a side table (#118517). /// An optimal encoding for inlined spans will need to be selected to minimize regressions. @@ -639,7 +776,7 @@ fn lockstep_iter_size( size.with(lockstep_iter_size(tt, interpolations, repeats)) }) } - TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => { + TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl { name, .. } => { let name = MacroRulesNormalizedIdent::new(*name); match lookup_cur_matched(name, interpolations, repeats) { Some(matched) => match matched { @@ -671,13 +808,13 @@ fn lockstep_iter_size( /// * `[ $( ${count(foo, 0)} ),* ]` will be the same as `[ $( ${count(foo)} ),* ]` /// * `[ $( ${count(foo, 1)} ),* ]` will return an error because `${count(foo, 1)}` is /// declared inside a single repetition and the index `1` implies two nested repetitions. -fn count_repetitions<'a>( - dcx: DiagCtxtHandle<'a>, +fn count_repetitions<'dx>( + dcx: DiagCtxtHandle<'dx>, depth_user: usize, mut matched: &NamedMatch, repeats: &[(usize, usize)], sp: &DelimSpan, -) -> PResult<'a, usize> { +) -> PResult<'dx, usize> { // Recursively count the number of matches in `matched` at given depth // (or at the top-level of `matched` if no depth is given). fn count<'a>(depth_curr: usize, depth_max: usize, matched: &NamedMatch) -> PResult<'a, usize> { @@ -762,102 +899,6 @@ fn out_of_bounds_err<'a>(dcx: DiagCtxtHandle<'a>, max: usize, span: Span, ty: &s dcx.struct_span_err(span, msg) } -fn transcribe_metavar_expr<'a>( - dcx: DiagCtxtHandle<'a>, - expr: &MetaVarExpr, - interp: &FxHashMap, - marker: &mut Marker, - repeats: &[(usize, usize)], - result: &mut Vec, - sp: &DelimSpan, - symbol_gallery: &SymbolGallery, -) -> PResult<'a, ()> { - let mut visited_span = || { - let mut span = sp.entire(); - marker.mark_span(&mut span); - span - }; - match *expr { - MetaVarExpr::Concat(ref elements) => { - let mut concatenated = String::new(); - for element in elements.into_iter() { - let symbol = match element { - MetaVarExprConcatElem::Ident(elem) => elem.name, - MetaVarExprConcatElem::Literal(elem) => *elem, - MetaVarExprConcatElem::Var(ident) => { - match matched_from_ident(dcx, *ident, interp)? { - NamedMatch::MatchedSeq(named_matches) => { - let Some((curr_idx, _)) = repeats.last() else { - return Err(dcx.struct_span_err(sp.entire(), "invalid syntax")); - }; - match &named_matches[*curr_idx] { - // FIXME(c410-f3r) Nested repetitions are unimplemented - MatchedSeq(_) => unimplemented!(), - MatchedSingle(pnr) => { - extract_symbol_from_pnr(dcx, pnr, ident.span)? - } - } - } - NamedMatch::MatchedSingle(pnr) => { - extract_symbol_from_pnr(dcx, pnr, ident.span)? - } - } - } - }; - concatenated.push_str(symbol.as_str()); - } - let symbol = nfc_normalize(&concatenated); - let concatenated_span = visited_span(); - if !rustc_lexer::is_ident(symbol.as_str()) { - return Err(dcx.struct_span_err( - concatenated_span, - "`${concat(..)}` is not generating a valid identifier", - )); - } - symbol_gallery.insert(symbol, concatenated_span); - // The current implementation marks the span as coming from the macro regardless of - // contexts of the concatenated identifiers but this behavior may change in the - // future. - result.push(TokenTree::Token( - Token::from_ast_ident(Ident::new(symbol, concatenated_span)), - Spacing::Alone, - )); - } - MetaVarExpr::Count(original_ident, depth) => { - let matched = matched_from_ident(dcx, original_ident, interp)?; - let count = count_repetitions(dcx, depth, matched, repeats, sp)?; - let tt = TokenTree::token_alone( - TokenKind::lit(token::Integer, sym::integer(count), None), - visited_span(), - ); - result.push(tt); - } - MetaVarExpr::Ignore(original_ident) => { - // Used to ensure that `original_ident` is present in the LHS - let _ = matched_from_ident(dcx, original_ident, interp)?; - } - MetaVarExpr::Index(depth) => match repeats.iter().nth_back(depth) { - Some((index, _)) => { - result.push(TokenTree::token_alone( - TokenKind::lit(token::Integer, sym::integer(*index), None), - visited_span(), - )); - } - None => return Err(out_of_bounds_err(dcx, repeats.len(), sp.entire(), "index")), - }, - MetaVarExpr::Len(depth) => match repeats.iter().nth_back(depth) { - Some((_, length)) => { - result.push(TokenTree::token_alone( - TokenKind::lit(token::Integer, sym::integer(*length), None), - visited_span(), - )); - } - None => return Err(out_of_bounds_err(dcx, repeats.len(), sp.entire(), "len")), - }, - } - Ok(()) -} - /// Extracts an metavariable symbol that can be an identifier, a token tree or a literal. fn extract_symbol_from_pnr<'a>( dcx: DiagCtxtHandle<'a>, diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 2c486a02bdf1..6e1c6df4bcb4 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -339,9 +339,9 @@ impl MutVisitor for PlaceholderExpander { } } - fn visit_method_receiver_expr(&mut self, expr: &mut P) { + fn visit_method_receiver_expr(&mut self, expr: &mut ast::Expr) { match expr.kind { - ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_method_receiver_expr(), + ast::ExprKind::MacCall(_) => *expr = *self.remove(expr.id).make_method_receiver_expr(), _ => walk_expr(self, expr), } } diff --git a/compiler/rustc_expand/src/stats.rs b/compiler/rustc_expand/src/stats.rs index 6b2ad30dffd0..b4c4eac028fe 100644 --- a/compiler/rustc_expand/src/stats.rs +++ b/compiler/rustc_expand/src/stats.rs @@ -15,15 +15,11 @@ pub struct MacroStat { /// Number of uses of the macro. pub uses: usize, - /// Net increase in number of lines of code (when pretty-printed), i.e. - /// `lines(output) - lines(invocation)`. Can be negative because a macro - /// output may be smaller than the invocation. - pub lines: isize, + /// Number of lines of code (when pretty-printed). + pub lines: usize, - /// Net increase in number of lines of code (when pretty-printed), i.e. - /// `bytes(output) - bytes(invocation)`. Can be negative because a macro - /// output may be smaller than the invocation. - pub bytes: isize, + /// Number of bytes of code (when pretty-printed). + pub bytes: usize, } pub(crate) fn elems_to_string(elems: &SmallVec<[T; 1]>, f: impl Fn(&T) -> String) -> String { @@ -131,16 +127,12 @@ pub(crate) fn update_macro_stats( input: &str, fragment: &AstFragment, ) { - fn lines_and_bytes(s: &str) -> (usize, usize) { - (s.trim_end().split('\n').count(), s.len()) - } - // Measure the size of the output by pretty-printing it and counting // the lines and bytes. let name = Symbol::intern(&pprust::path_to_string(path)); let output = fragment.to_string(); - let (in_l, in_b) = lines_and_bytes(input); - let (out_l, out_b) = lines_and_bytes(&output); + let num_lines = output.trim_end().split('\n').count(); + let num_bytes = output.len(); // This code is useful for debugging `-Zmacro-stats`. For every // invocation it prints the full input and output. @@ -157,7 +149,7 @@ pub(crate) fn update_macro_stats( {name}: [{crate_name}] ({fragment_kind:?}) {span}\n\ -------------------------------\n\ {input}\n\ - -- ({in_l} lines, {in_b} bytes) --> ({out_l} lines, {out_b} bytes) --\n\ + -- {num_lines} lines, {num_bytes} bytes --\n\ {output}\n\ " ); @@ -166,6 +158,6 @@ pub(crate) fn update_macro_stats( // The recorded size is the difference between the input and the output. let entry = ecx.macro_stats.entry((name, macro_kind)).or_insert(MacroStat::default()); entry.uses += 1; - entry.lines += out_l as isize - in_l as isize; - entry.bytes += out_b as isize - in_b as isize; + entry.lines += num_lines; + entry.bytes += num_bytes; } diff --git a/compiler/rustc_feature/Cargo.toml b/compiler/rustc_feature/Cargo.toml index a5ae06473cbe..78d7b698b720 100644 --- a/compiler/rustc_feature/Cargo.toml +++ b/compiler/rustc_feature/Cargo.toml @@ -5,8 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start +rustc_attr_data_structures = { path = "../rustc_attr_data_structures" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_span = { path = "../rustc_span" } -serde = { version = "1.0.125", features = [ "derive" ] } +serde = { version = "1.0.125", features = ["derive"] } serde_json = "1.0.59" # tidy-alphabetical-end diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index b5218ec267cc..8e1392998d40 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -5,6 +5,7 @@ use std::sync::LazyLock; use AttributeDuplicates::*; use AttributeGate::*; use AttributeType::*; +use rustc_attr_data_structures::EncodeCrossCrate; use rustc_data_structures::fx::FxHashMap; use rustc_span::edition::Edition; use rustc_span::{Symbol, sym}; @@ -368,12 +369,6 @@ macro_rules! experimental { }; } -#[derive(PartialEq)] -pub enum EncodeCrossCrate { - Yes, - No, -} - pub struct BuiltinAttribute { pub name: Symbol, /// Whether this attribute is encode cross crate. @@ -495,6 +490,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), @@ -656,6 +652,19 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::Yes, min_generic_const_args, experimental!(type_const), ), + // The `#[loop_match]` and `#[const_continue]` attributes are part of the + // lang experiment for RFC 3720 tracked in: + // + // - https://github.com/rust-lang/rust/issues/132306 + gated!( + const_continue, Normal, template!(Word), ErrorFollowing, + EncodeCrossCrate::No, loop_match, experimental!(const_continue) + ), + gated!( + loop_match, Normal, template!(Word), ErrorFollowing, + EncodeCrossCrate::No, loop_match, experimental!(loop_match) + ), + // ========================================================================== // Internal attributes: Stability, deprecation, and unsafe: // ========================================================================== @@ -709,7 +718,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), rustc_attr!( rustc_pub_transparent, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::Yes, + ErrorFollowing, EncodeCrossCrate::Yes, "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation", ), @@ -1082,7 +1091,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "the `#[rustc_main]` attribute is used internally to specify test entry point function", ), rustc_attr!( - rustc_skip_during_method_dispatch, Normal, template!(List: "array, boxed_slice"), WarnFollowing, + rustc_skip_during_method_dispatch, Normal, template!(List: "array, boxed_slice"), ErrorFollowing, EncodeCrossCrate::No, "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \ from method dispatch when the receiver is of the following type, for compatibility in \ diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 0cd090b25a4f..ddb99585bc24 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -54,6 +54,7 @@ declare_features! ( /// Allows using the `amdgpu-kernel` ABI. (removed, abi_amdgpu_kernel, "1.77.0", Some(51575), None, 120495), + (removed, abi_c_cmse_nonsecure_call, "CURRENT_RUSTC_VERSION", Some(81391), Some("renamed to abi_cmse_nonsecure_call"), 142146), (removed, advanced_slice_patterns, "1.42.0", Some(62254), Some("merged into `#![feature(slice_patterns)]`"), 67712), (removed, allocator, "1.0.0", None, None), @@ -285,4 +286,18 @@ declare_features! ( // ------------------------------------------------------------------------- // feature-group-end: removed features // ------------------------------------------------------------------------- + + + // ------------------------------------------------------------------------- + // feature-group-start: removed library features + // ------------------------------------------------------------------------- + // + // FIXME(#141617): we should have a better way to track removed library features, but we reuse + // the infrastructure here so users still get hints. The symbols used here can be remove from + // `symbol.rs` when that happens. + (removed, concat_idents, "CURRENT_RUSTC_VERSION", Some(29599), + Some("use the `${concat(..)}` metavariable expression instead"), 142704), + // ------------------------------------------------------------------------- + // feature-group-end: removed library features + // ------------------------------------------------------------------------- ); diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index a7bc6207149f..e73a4e1766ce 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -353,8 +353,8 @@ declare_features! ( /// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`. (unstable, abi_avr_interrupt, "1.45.0", Some(69664)), - /// Allows `extern "C-cmse-nonsecure-call" fn()`. - (unstable, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391)), + /// Allows `extern "cmse-nonsecure-call" fn()`. + (unstable, abi_cmse_nonsecure_call, "CURRENT_RUSTC_VERSION", Some(81391)), /// Allows `extern "custom" fn()`. (unstable, abi_custom, "CURRENT_RUSTC_VERSION", Some(140829)), /// Allows `extern "gpu-kernel" fn()`. @@ -431,7 +431,7 @@ declare_features! ( (unstable, closure_lifetime_binder, "1.64.0", Some(97362)), /// Allows `#[track_caller]` on closures and coroutines. (unstable, closure_track_caller, "1.57.0", Some(87417)), - /// Allows `extern "C-cmse-nonsecure-entry" fn()`. + /// Allows `extern "cmse-nonsecure-entry" fn()`. (unstable, cmse_nonsecure_entry, "1.48.0", Some(75835)), /// Allows `async {}` expressions in const contexts. (unstable, const_async_blocks, "1.53.0", Some(85368)), @@ -510,7 +510,7 @@ declare_features! ( (unstable, ffi_pure, "1.45.0", Some(58329)), /// Controlling the behavior of fmt::Debug (unstable, fmt_debug, "1.82.0", Some(129709)), - /// Allows using `#[repr(align(...))]` on function items + /// Allows using `#[align(...)]` on function items (unstable, fn_align, "1.53.0", Some(82232)), /// Support delegating implementation of functions to other already implemented functions. (incomplete, fn_delegation, "1.76.0", Some(118212)), @@ -557,6 +557,8 @@ declare_features! ( /// Allows using `#[link(kind = "link-arg", name = "...")]` /// to pass custom arguments to the linker. (unstable, link_arg_attribute, "1.76.0", Some(99427)), + /// Allows fused `loop`/`match` for direct intraprocedural jumps. + (incomplete, loop_match, "CURRENT_RUSTC_VERSION", Some(132306)), /// Give access to additional metadata about declarative macro meta-variables. (unstable, macro_metavar_expr, "1.61.0", Some(83527)), /// Provides a way to concatenate identifiers using metavariable expressions. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 556f50a85af7..679904c7cfe4 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1302,6 +1302,7 @@ impl AttributeExt for Attribute { // FIXME: should not be needed anymore when all attrs are parsed Attribute::Parsed(AttributeKind::Deprecation { span, .. }) => *span, Attribute::Parsed(AttributeKind::DocComment { span, .. }) => *span, + Attribute::Parsed(AttributeKind::MayDangle(span)) => *span, a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"), } } @@ -1345,12 +1346,13 @@ impl AttributeExt for Attribute { } } - #[inline] - fn style(&self) -> AttrStyle { - match &self { - Attribute::Unparsed(u) => u.style, - Attribute::Parsed(AttributeKind::DocComment { style, .. }) => *style, - _ => panic!(), + fn doc_resolution_scope(&self) -> Option { + match self { + Attribute::Parsed(AttributeKind::DocComment { style, .. }) => Some(*style), + Attribute::Unparsed(attr) if self.has_name(sym::doc) && self.value_str().is_some() => { + Some(attr.style) + } + _ => None, } } } @@ -1441,11 +1443,6 @@ impl Attribute { pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> { AttributeExt::doc_str_and_comment_kind(self) } - - #[inline] - pub fn style(&self) -> AttrStyle { - AttributeExt::style(self) - } } /// Attributes owned by a HIR owner. @@ -2285,16 +2282,9 @@ pub struct Expr<'hir> { } impl Expr<'_> { - pub fn precedence( - &self, - for_each_attr: &dyn Fn(HirId, &mut dyn FnMut(&Attribute)), - ) -> ExprPrecedence { + pub fn precedence(&self, has_attr: &dyn Fn(HirId) -> bool) -> ExprPrecedence { let prefix_attrs_precedence = || -> ExprPrecedence { - let mut has_outer_attr = false; - for_each_attr(self.hir_id, &mut |attr: &Attribute| { - has_outer_attr |= matches!(attr.style(), AttrStyle::Outer) - }); - if has_outer_attr { ExprPrecedence::Prefix } else { ExprPrecedence::Unambiguous } + if has_attr(self.hir_id) { ExprPrecedence::Prefix } else { ExprPrecedence::Unambiguous } }; match &self.kind { @@ -2350,7 +2340,7 @@ impl Expr<'_> { | ExprKind::Use(..) | ExprKind::Err(_) => prefix_attrs_precedence(), - ExprKind::DropTemps(expr, ..) => expr.precedence(for_each_attr), + ExprKind::DropTemps(expr, ..) => expr.precedence(has_attr), } } diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index f768bd157abc..4ec2bbfc5abe 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -1,5 +1,5 @@ hir_analysis_abi_custom_clothed_function = - items with the `"custom"` ABI can only be declared externally or defined via naked functions + items with the "custom" ABI can only be declared externally or defined via naked functions .suggestion = convert this to an `#[unsafe(naked)]` function hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_ident}` in bounds of `{$qself}` @@ -46,6 +46,9 @@ hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the {$ hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes +hir_analysis_async_drop_without_sync_drop = `AsyncDrop` impl without `Drop` impl + .help = type implementing `AsyncDrop` trait must also implement `Drop` trait to be used in sync context and unwinds + hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}` .label = deref recursion limit reached .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) @@ -70,10 +73,10 @@ hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are fo .label = `for<...>` is here hir_analysis_cmse_call_generic = - function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type + function pointers with the `"cmse-nonsecure-call"` ABI cannot contain generics in their type hir_analysis_cmse_entry_generic = - functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type + functions with the `"cmse-nonsecure-entry"` ABI cannot contain generics in their type hir_analysis_cmse_inputs_stack_spill = arguments for `{$abi}` function too large to pass via registers diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 32fec0604c0f..485dd1d22044 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1,8 +1,9 @@ use std::cell::LazyCell; use std::ops::ControlFlow; -use rustc_abi::FieldIdx; +use rustc_abi::{ExternAbi, FieldIdx}; use rustc_attr_data_structures::ReprAttr::ReprPacked; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; use rustc_errors::{EmissionGuarantee, MultiSpan}; @@ -12,7 +13,6 @@ use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, ObligationCauseCode}; use rustc_lint_defs::builtin::{ REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_CALLING_CONVENTIONS, - UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, }; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; @@ -52,49 +52,22 @@ fn add_abi_diag_help(abi: ExternAbi, diag: &mut Diag<'_, T } pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi) { - // FIXME: this should be checked earlier, e.g. in `rustc_ast_lowering`, to fix - // things like #86232. + // FIXME: This should be checked earlier, e.g. in `rustc_ast_lowering`, as this + // currently only guards function imports, function definitions, and function pointer types. + // Functions in trait declarations can still use "deprecated" ABIs without any warning. match AbiMap::from_target(&tcx.sess.target).canonize_abi(abi, false) { AbiMapping::Direct(..) => (), + // already erred in rustc_ast_lowering AbiMapping::Invalid => { - let mut err = struct_span_code_err!( - tcx.dcx(), - span, - E0570, - "`{abi}` is not a supported ABI for the current target", - ); - add_abi_diag_help(abi, &mut err); - err.emit(); + tcx.dcx().span_delayed_bug(span, format!("{abi} should be rejected in ast_lowering")); } AbiMapping::Deprecated(..) => { tcx.node_span_lint(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| { - lint.primary_message("use of calling convention not supported on this target"); - add_abi_diag_help(abi, lint); - }); - } - } -} - -pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi) { - // This is always an FCW, even for `AbiMapping::Invalid`, since we started linting later than - // in `check_abi` above. - match AbiMap::from_target(&tcx.sess.target).canonize_abi(abi, false) { - AbiMapping::Direct(..) => (), - // This is not a redundant match arm: these ABIs started linting after introducing - // UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS already existed and we want to - // avoid expanding the scope of that lint so it can move to a hard error sooner. - AbiMapping::Deprecated(..) => { - tcx.node_span_lint(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| { - lint.primary_message("use of calling convention not supported on this target"); - add_abi_diag_help(abi, lint); - }); - } - AbiMapping::Invalid => { - tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| { lint.primary_message(format!( - "the calling convention {abi} is not supported on this target" + "{abi} is not a supported ABI for the current target" )); + add_abi_diag_help(abi, lint); }); } } @@ -103,7 +76,7 @@ pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ex pub fn check_custom_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, fn_sig: FnSig<'_>, fn_sig_span: Span) { if fn_sig.abi == ExternAbi::Custom { // Function definitions that use `extern "custom"` must be naked functions. - if !tcx.has_attr(def_id, sym::naked) { + if !find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Naked(_)) { tcx.dcx().emit_err(crate::errors::AbiCustomClothedFunction { span: fn_sig_span, naked_span: tcx.def_span(def_id).shrink_to_lo(), @@ -867,6 +840,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { let hir::ItemKind::ForeignMod { abi, items } = it.kind else { return; }; + check_abi(tcx, it.hir_id(), it.span, abi); for item in items { @@ -1384,7 +1358,11 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)), ty::Array(ty, _) => check_non_exhaustive(tcx, *ty), ty::Adt(def, args) => { - if !def.did().is_local() && !tcx.has_attr(def.did(), sym::rustc_pub_transparent) + if !def.did().is_local() + && !attrs::find_attr!( + tcx.get_all_attrs(def.did()), + AttributeKind::PubTransparent(_) + ) { let non_exhaustive = def.is_variant_list_non_exhaustive() || def diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 3bad36da9990..b556683e80a5 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -1,14 +1,15 @@ use std::ops::Not; use rustc_abi::ExternAbi; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_hir as hir; use rustc_hir::Node; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::span_bug; use rustc_middle::ty::{self, TyCtxt, TypingMode}; use rustc_session::config::EntryFnType; +use rustc_span::Span; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; -use rustc_span::{Span, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; @@ -98,8 +99,10 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { error = true; } - for attr in tcx.get_attrs(main_def_id, sym::track_caller) { - tcx.dcx().emit_err(errors::TrackCallerOnMain { span: attr.span(), annotated: main_span }); + if let Some(attr_span) = + find_attr!(tcx.get_all_attrs(main_def_id), AttributeKind::TrackCaller(span) => *span) + { + tcx.dcx().emit_err(errors::TrackCallerOnMain { span: attr_span, annotated: main_span }); error = true; } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 5b8aa28102c7..5cec3331bb19 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -72,8 +72,8 @@ pub mod wfcheck; use std::num::NonZero; -pub use check::{check_abi, check_abi_fn_ptr, check_custom_abi}; -use rustc_abi::{ExternAbi, VariantIdx}; +pub use check::{check_abi, check_custom_abi}; +use rustc_abi::VariantIdx; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::{Diag, ErrorGuaranteed, pluralize, struct_span_code_err}; use rustc_hir::LangItem; @@ -114,7 +114,15 @@ pub fn provide(providers: &mut Providers) { } fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - tcx.calculate_dtor(def_id, always_applicable::check_drop_impl) + let dtor = tcx.calculate_dtor(def_id, always_applicable::check_drop_impl); + if dtor.is_none() && tcx.features().async_drop() { + if let Some(async_dtor) = adt_async_destructor(tcx, def_id) { + // When type has AsyncDrop impl, but doesn't have Drop impl, generate error + let span = tcx.def_span(async_dtor.impl_did); + tcx.dcx().emit_err(errors::AsyncDropWithoutSyncDrop { span }); + } + } + dtor } fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { @@ -303,9 +311,7 @@ fn default_body_is_unstable( reason: reason_str, }); - let inject_span = item_did - .as_local() - .and_then(|id| tcx.crate_level_attribute_injection_span(tcx.local_def_id_to_hir_id(id))); + let inject_span = item_did.is_local().then(|| tcx.crate_level_attribute_injection_span()); rustc_session::parse::add_feature_diagnostics_for_issue( &mut err, &tcx.sess, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 20d0e87b7a76..d05e381f8c86 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -382,8 +382,6 @@ fn check_trait_item<'tcx>( _ => (None, trait_item.span), }; - check_dyn_incompatible_self_trait_by_name(tcx, trait_item); - // Check that an item definition in a subtrait is shadowing a supertrait item. lint_item_shadowing_supertrait_item(tcx, def_id); @@ -832,70 +830,6 @@ impl<'tcx> TypeVisitor> for GATArgsCollector<'tcx> { } } -fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool { - match ty.kind { - hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments { - [s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()), - _ => false, - }, - _ => false, - } -} - -/// Detect when a dyn-incompatible trait is referring to itself in one of its associated items. -/// -/// In such cases, suggest using `Self` instead. -fn check_dyn_incompatible_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) { - let (trait_ident, trait_def_id) = - match tcx.hir_node_by_def_id(tcx.hir_get_parent_item(item.hir_id()).def_id) { - hir::Node::Item(item) => match item.kind { - hir::ItemKind::Trait(_, _, ident, ..) => (ident, item.owner_id), - _ => return, - }, - _ => return, - }; - let mut trait_should_be_self = vec![]; - match &item.kind { - hir::TraitItemKind::Const(ty, _) | hir::TraitItemKind::Type(_, Some(ty)) - if could_be_self(trait_def_id.def_id, ty) => - { - trait_should_be_self.push(ty.span) - } - hir::TraitItemKind::Fn(sig, _) => { - for ty in sig.decl.inputs { - if could_be_self(trait_def_id.def_id, ty) { - trait_should_be_self.push(ty.span); - } - } - match sig.decl.output { - hir::FnRetTy::Return(ty) if could_be_self(trait_def_id.def_id, ty) => { - trait_should_be_self.push(ty.span); - } - _ => {} - } - } - _ => {} - } - if !trait_should_be_self.is_empty() { - if tcx.is_dyn_compatible(trait_def_id) { - return; - } - let sugg = trait_should_be_self.iter().map(|span| (*span, "Self".to_string())).collect(); - tcx.dcx() - .struct_span_err( - trait_should_be_self, - "associated item referring to unboxed trait object for its own trait", - ) - .with_span_label(trait_ident.span, "in this trait") - .with_multipart_suggestion( - "you might have meant to use `Self` to refer to the implementing type", - sugg, - Applicability::MachineApplicable, - ) - .emit(); - } -} - fn lint_item_shadowing_supertrait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_def_id: LocalDefId) { let item_name = tcx.item_name(trait_item_def_id.to_def_id()); let trait_def_id = tcx.local_parent(trait_item_def_id); @@ -1064,7 +998,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), Ok(..) => Some(vec![(adt_const_params_feature_string, sym::adt_const_params)]), }; if let Some(features) = may_suggest_feature { - tcx.disabled_nightly_features(&mut diag, Some(param.hir_id), features); + tcx.disabled_nightly_features(&mut diag, features); } Err(diag.emit()) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 6e22ac5a28a8..c967e87bfd87 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -21,6 +21,7 @@ use std::ops::Bound; use rustc_abi::ExternAbi; use rustc_ast::Recovered; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::unord::UnordMap; use rustc_errors::{ @@ -34,16 +35,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 +371,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, + ) -> (Vec, Vec>) { + 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 Foo` to unify with `Foo::IAT`, while also disallowing + // `Foo::IAT` from unifying with `impl Foo`. + // + // 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 Foo` would + // be considered a valid candidate when resolving `Foo::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, @@ -1093,22 +1152,11 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive); let is_fundamental = tcx.has_attr(def_id, sym::fundamental); - // FIXME: We could probably do way better attribute validation here. - let mut skip_array_during_method_dispatch = false; - let mut skip_boxed_slice_during_method_dispatch = false; - for attr in tcx.get_attrs(def_id, sym::rustc_skip_during_method_dispatch) { - if let Some(lst) = attr.meta_item_list() { - for item in lst { - if let Some(ident) = item.ident() { - match ident.as_str() { - "array" => skip_array_during_method_dispatch = true, - "boxed_slice" => skip_boxed_slice_during_method_dispatch = true, - _ => (), - } - } - } - } - } + let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = find_attr!( + tcx.get_all_attrs(def_id), + AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span:_ } => [*array, *boxed_slice] + ) + .unwrap_or([false; 2]); let specialization_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) { ty::trait_def::TraitSpecializationKind::Marker diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index d45f0475e991..95743f9a63eb 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -2177,84 +2177,80 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { /// Walk the generics of the item for a trait bound whose self type /// corresponds to the expected res, and return the trait def id. fn for_each_trait_bound_on_res(&self, expected_res: Res) -> impl Iterator { - std::iter::from_coroutine( - #[coroutine] - move || { - let mut scope = self.scope; - loop { - let hir_id = match *scope { - Scope::Binder { hir_id, .. } => Some(hir_id), - Scope::Root { opt_parent_item: Some(parent_def_id) } => { - Some(self.tcx.local_def_id_to_hir_id(parent_def_id)) - } - Scope::Body { .. } - | Scope::ObjectLifetimeDefault { .. } - | Scope::Supertrait { .. } - | Scope::TraitRefBoundary { .. } - | Scope::LateBoundary { .. } - | Scope::Opaque { .. } - | Scope::Root { opt_parent_item: None } => None, - }; + gen move { + let mut scope = self.scope; + loop { + let hir_id = match *scope { + Scope::Binder { hir_id, .. } => Some(hir_id), + Scope::Root { opt_parent_item: Some(parent_def_id) } => { + Some(self.tcx.local_def_id_to_hir_id(parent_def_id)) + } + Scope::Body { .. } + | Scope::ObjectLifetimeDefault { .. } + | Scope::Supertrait { .. } + | Scope::TraitRefBoundary { .. } + | Scope::LateBoundary { .. } + | Scope::Opaque { .. } + | Scope::Root { opt_parent_item: None } => None, + }; - if let Some(hir_id) = hir_id { - let node = self.tcx.hir_node(hir_id); - // If this is a `Self` bound in a trait, yield the trait itself. - // Specifically, we don't need to look at any supertraits since - // we already do that in `BoundVarContext::supertrait_hrtb_vars`. - if let Res::SelfTyParam { trait_: _ } = expected_res - && let hir::Node::Item(item) = node - && let hir::ItemKind::Trait(..) = item.kind - { - // Yield the trait's def id. Supertraits will be - // elaborated from that. - yield item.owner_id.def_id.to_def_id(); - } else if let Some(generics) = node.generics() { - for pred in generics.predicates { - let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind - else { - continue; - }; - let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) = - pred.bounded_ty.kind - else { - continue; - }; - // Match the expected res. - if bounded_path.res != expected_res { - continue; - } - for pred in pred.bounds { - match pred { - hir::GenericBound::Trait(poly_trait_ref) => { - if let Some(def_id) = - poly_trait_ref.trait_ref.trait_def_id() - { - yield def_id; - } + if let Some(hir_id) = hir_id { + let node = self.tcx.hir_node(hir_id); + // If this is a `Self` bound in a trait, yield the trait itself. + // Specifically, we don't need to look at any supertraits since + // we already do that in `BoundVarContext::supertrait_hrtb_vars`. + if let Res::SelfTyParam { trait_: _ } = expected_res + && let hir::Node::Item(item) = node + && let hir::ItemKind::Trait(..) = item.kind + { + // Yield the trait's def id. Supertraits will be + // elaborated from that. + yield item.owner_id.def_id.to_def_id(); + } else if let Some(generics) = node.generics() { + for pred in generics.predicates { + let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else { + continue; + }; + let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) = + pred.bounded_ty.kind + else { + continue; + }; + // Match the expected res. + if bounded_path.res != expected_res { + continue; + } + for pred in pred.bounds { + match pred { + hir::GenericBound::Trait(poly_trait_ref) => { + if let Some(def_id) = + poly_trait_ref.trait_ref.trait_def_id() + { + yield def_id; } - hir::GenericBound::Outlives(_) - | hir::GenericBound::Use(_, _) => {} } + hir::GenericBound::Outlives(_) + | hir::GenericBound::Use(_, _) => {} } } } } - - match *scope { - Scope::Binder { s, .. } - | Scope::Body { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } - | Scope::Supertrait { s, .. } - | Scope::TraitRefBoundary { s } - | Scope::LateBoundary { s, .. } - | Scope::Opaque { s, .. } => { - scope = s; - } - Scope::Root { .. } => break, - } } - }, - ) + + match *scope { + Scope::Binder { s, .. } + | Scope::Body { s, .. } + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s } + | Scope::LateBoundary { s, .. } + | Scope::Opaque { s, .. } => { + scope = s; + } + Scope::Root { .. } => break, + } + } + } } } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 8de2aec95a7b..c920e25ad376 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -127,6 +127,7 @@ pub(crate) enum AssocItemNotFoundSugg<'a> { SimilarInOtherTrait { #[primary_span] span: Span, + trait_name: &'a str, assoc_kind: &'static str, suggested_name: Symbol, }, @@ -1712,3 +1713,11 @@ pub(crate) struct AbiCustomClothedFunction { )] pub naked_span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_async_drop_without_sync_drop)] +#[help] +pub(crate) struct AsyncDropWithoutSyncDrop { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index ebeb3b58208e..82e5f65476ff 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -18,7 +18,7 @@ pub(crate) fn validate_cmse_abi<'tcx>( fn_sig: ty::PolyFnSig<'tcx>, ) { match abi { - ExternAbi::CCmseNonSecureCall => { + ExternAbi::CmseNonSecureCall => { let hir_node = tcx.hir_node(hir_id); let hir::Node::Ty(hir::Ty { span: bare_fn_span, @@ -38,7 +38,7 @@ pub(crate) fn validate_cmse_abi<'tcx>( dcx, span, E0781, - "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" + "the `\"cmse-nonsecure-call\"` ABI is only allowed on function pointers" ) .emit(); return; @@ -78,7 +78,7 @@ pub(crate) fn validate_cmse_abi<'tcx>( } }; } - ExternAbi::CCmseNonSecureEntry => { + ExternAbi::CmseNonSecureEntry => { let hir_node = tcx.hir_node(hir_id); let Some(hir::FnSig { decl, span: fn_sig_span, .. }) = hir_node.fn_sig() else { // might happen when this ABI is used incorrectly. That will be handled elsewhere @@ -203,11 +203,11 @@ fn should_emit_generic_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError match layout_err { TooGeneric(ty) => { match abi { - ExternAbi::CCmseNonSecureCall => { + ExternAbi::CmseNonSecureCall => { // prevent double reporting of this error !ty.is_impl_trait() } - ExternAbi::CCmseNonSecureEntry => true, + ExternAbi::CmseNonSecureEntry => true, _ => bug!("invalid ABI: {abi}"), } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 1cda6dff21e9..f211137ddd6a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -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, @@ -308,6 +309,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // change the associated item. err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait { span: assoc_ident.span, + trait_name: &trait_name, assoc_kind: assoc_kind_str, suggested_name, }); @@ -793,7 +795,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, name: Ident, self_ty: Ty<'tcx>, - candidates: Vec<(DefId, (DefId, DefId))>, + candidates: Vec, fulfillment_errors: Vec>, span: Span, assoc_tag: ty::AssocTag, @@ -827,8 +829,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::>() .join("\n"); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index bf407cbaccb5..51cd1b7704d8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -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,10 +48,10 @@ 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; +use crate::check::check_abi; use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; @@ -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, + ) -> (Vec, Vec>); + /// 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. @@ -1661,7 +1588,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &infcx_ }; - tcx.all_traits() + tcx.all_traits_including_private() .filter(|trait_def_id| { // Consider only traits with the associated type tcx.associated_items(*trait_def_id) @@ -2733,7 +2660,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(bare_fn_ty), span, .. }) = tcx.hir_node(hir_id) { - check_abi_fn_ptr(tcx, hir_id, *span, bare_fn_ty.abi); + check_abi(tcx, hir_id, *span, bare_fn_ty.abi); } // reject function types that violate cmse ABI requirements diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 4633f3951a78..fef0dbf2ece9 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -1,7 +1,8 @@ +use rustc_hir::def::DefKind; use rustc_hir::intravisit::{self, Visitor, VisitorExt}; use rustc_hir::{self as hir, AmbigArg, ForeignItem, ForeignItemKind}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::{ObligationCause, WellFormedLoc}; +use rustc_infer::traits::{ObligationCause, ObligationCauseCode, WellFormedLoc}; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode, fold_regions}; @@ -107,6 +108,17 @@ fn diagnostic_hir_wf_check<'tcx>( // over less-specific types (e.g. `Option>`) if self.depth >= self.cause_depth { self.cause = Some(error.obligation.cause); + if let hir::TyKind::TraitObject(..) = ty.kind { + if let DefKind::AssocTy | DefKind::AssocConst | DefKind::AssocFn = + self.tcx.def_kind(self.def_id) + { + self.cause = Some(ObligationCause::new( + ty.span, + self.def_id, + ObligationCauseCode::DynCompatible(ty.span), + )); + } + } self.cause_depth = self.depth } } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 7c8c9425a03d..76ab2e57a1b5 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -62,8 +62,8 @@ This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] -#![feature(coroutines)] #![feature(debug_closure_helpers)] +#![feature(gen_blocks)] #![feature(if_let_guard)] #![feature(iter_from_coroutine)] #![feature(iter_intersperse)] diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index fc507285860e..ff87d3dec6e9 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -10,7 +10,7 @@ use std::vec; use rustc_abi::ExternAbi; use rustc_ast::util::parser::{self, ExprPrecedence, Fixity}; -use rustc_ast::{AttrStyle, DUMMY_NODE_ID, DelimArgs}; +use rustc_ast::{DUMMY_NODE_ID, DelimArgs}; use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent}; use rustc_ast_pretty::pp::{self, BoxMarker, Breaks}; use rustc_ast_pretty::pprust::state::MacHeader; @@ -22,7 +22,7 @@ use rustc_hir::{ TyPatKind, }; use rustc_span::source_map::SourceMap; -use rustc_span::{FileName, Ident, Span, Symbol, kw}; +use rustc_span::{FileName, Ident, Span, Symbol, kw, sym}; use {rustc_ast as ast, rustc_hir as hir}; pub fn id_to_string(cx: &dyn rustc_hir::intravisit::HirTyCtxt<'_>, hir_id: HirId) -> String { @@ -81,32 +81,24 @@ impl<'a> State<'a> { } fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence { - let for_each_attr = |id: HirId, callback: &mut dyn FnMut(&hir::Attribute)| { - self.attrs(id).iter().for_each(callback); - }; - expr.precedence(&for_each_attr) + let has_attr = |id: HirId| !self.attrs(id).is_empty(); + expr.precedence(&has_attr) } - fn print_attrs_as_inner(&mut self, attrs: &[hir::Attribute]) { - self.print_either_attributes(attrs, ast::AttrStyle::Inner) - } - - fn print_attrs_as_outer(&mut self, attrs: &[hir::Attribute]) { - self.print_either_attributes(attrs, ast::AttrStyle::Outer) - } - - fn print_either_attributes(&mut self, attrs: &[hir::Attribute], style: ast::AttrStyle) { + fn print_attrs(&mut self, attrs: &[hir::Attribute]) { if attrs.is_empty() { return; } for attr in attrs { - self.print_attribute_inline(attr, style); + self.print_attribute_as_style(attr, ast::AttrStyle::Outer); } self.hardbreak_if_not_bol(); } - fn print_attribute_inline(&mut self, attr: &hir::Attribute, style: AttrStyle) { + /// Print a single attribute as if it has style `style`, disregarding the + /// actual style of the attribute. + fn print_attribute_as_style(&mut self, attr: &hir::Attribute, style: ast::AttrStyle) { match &attr { hir::Attribute::Unparsed(unparsed) => { self.maybe_print_comment(unparsed.span.lo()); @@ -118,14 +110,17 @@ impl<'a> State<'a> { self.word("]"); self.hardbreak() } - hir::Attribute::Parsed(AttributeKind::DocComment { style, kind, comment, .. }) => { + hir::Attribute::Parsed(AttributeKind::DocComment { kind, comment, .. }) => { self.word(rustc_ast_pretty::pprust::state::doc_comment_to_string( - *kind, *style, *comment, + *kind, style, *comment, )); self.hardbreak() } hir::Attribute::Parsed(pa) => { - self.word("#[attr = "); + match style { + ast::AttrStyle::Inner => self.word("#![attr = "), + ast::AttrStyle::Outer => self.word("#[attr = "), + } pa.print_attribute(self); self.word("]"); self.hardbreak() @@ -281,10 +276,17 @@ pub fn print_crate<'a>( ann, }; + // Print all attributes, regardless of actual style, as inner attributes + // since this is the crate root with nothing above it to print outer + // attributes. + for attr in s.attrs(hir::CRATE_HIR_ID) { + s.print_attribute_as_style(attr, ast::AttrStyle::Inner); + } + // When printing the AST, we sometimes need to inject `#[no_std]` here. // Since you can't compile the HIR, it's not necessary. - s.print_mod(krate, (*attrs)(hir::CRATE_HIR_ID)); + s.print_mod(krate); s.print_remaining_comments(); s.s.eof() } @@ -299,7 +301,7 @@ where } pub fn attribute_to_string(ann: &dyn PpAnn, attr: &hir::Attribute) -> String { - to_string(ann, |s| s.print_attribute_inline(attr, AttrStyle::Outer)) + to_string(ann, |s| s.print_attribute_as_style(attr, ast::AttrStyle::Outer)) } pub fn ty_to_string(ann: &dyn PpAnn, ty: &hir::Ty<'_>) -> String { @@ -361,8 +363,7 @@ impl<'a> State<'a> { self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span); } - fn print_mod(&mut self, _mod: &hir::Mod<'_>, attrs: &[hir::Attribute]) { - self.print_attrs_as_inner(attrs); + fn print_mod(&mut self, _mod: &hir::Mod<'_>) { for &item_id in _mod.item_ids { self.ann.nested(self, Nested::Item(item_id)); } @@ -479,7 +480,7 @@ impl<'a> State<'a> { fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) { self.hardbreak_if_not_bol(); self.maybe_print_comment(item.span.lo()); - self.print_attrs_as_outer(self.attrs(item.hir_id())); + self.print_attrs(self.attrs(item.hir_id())); match item.kind { hir::ForeignItemKind::Fn(sig, arg_idents, generics) => { let (cb, ib) = self.head(""); @@ -565,7 +566,7 @@ impl<'a> State<'a> { self.hardbreak_if_not_bol(); self.maybe_print_comment(item.span.lo()); let attrs = self.attrs(item.hir_id()); - self.print_attrs_as_outer(attrs); + self.print_attrs(attrs); self.ann.pre(self, AnnNode::Item(item)); match item.kind { hir::ItemKind::ExternCrate(orig_name, ident) => { @@ -647,14 +648,13 @@ impl<'a> State<'a> { self.print_ident(ident); self.nbsp(); self.bopen(ib); - self.print_mod(mod_, attrs); + self.print_mod(mod_); self.bclose(item.span, cb); } hir::ItemKind::ForeignMod { abi, items } => { let (cb, ib) = self.head("extern"); self.word_nbsp(abi.to_string()); self.bopen(ib); - self.print_attrs_as_inner(self.attrs(item.hir_id())); for item in items { self.ann.nested(self, Nested::ForeignItem(item.id)); } @@ -731,7 +731,6 @@ impl<'a> State<'a> { self.space(); self.bopen(ib); - self.print_attrs_as_inner(attrs); for impl_item in items { self.ann.nested(self, Nested::ImplItem(impl_item.id)); } @@ -822,7 +821,7 @@ impl<'a> State<'a> { for v in variants { self.space_if_not_bol(); self.maybe_print_comment(v.span.lo()); - self.print_attrs_as_outer(self.attrs(v.hir_id)); + self.print_attrs(self.attrs(v.hir_id)); let ib = self.ibox(INDENT_UNIT); self.print_variant(v); self.word(","); @@ -857,7 +856,7 @@ impl<'a> State<'a> { self.popen(); self.commasep(Inconsistent, struct_def.fields(), |s, field| { s.maybe_print_comment(field.span.lo()); - s.print_attrs_as_outer(s.attrs(field.hir_id)); + s.print_attrs(s.attrs(field.hir_id)); s.print_type(field.ty); }); self.pclose(); @@ -878,7 +877,7 @@ impl<'a> State<'a> { for field in struct_def.fields() { self.hardbreak_if_not_bol(); self.maybe_print_comment(field.span.lo()); - self.print_attrs_as_outer(self.attrs(field.hir_id)); + self.print_attrs(self.attrs(field.hir_id)); self.print_ident(field.ident); self.word_nbsp(":"); self.print_type(field.ty); @@ -916,7 +915,7 @@ impl<'a> State<'a> { self.ann.pre(self, AnnNode::SubItem(ti.hir_id())); self.hardbreak_if_not_bol(); self.maybe_print_comment(ti.span.lo()); - self.print_attrs_as_outer(self.attrs(ti.hir_id())); + self.print_attrs(self.attrs(ti.hir_id())); match ti.kind { hir::TraitItemKind::Const(ty, default) => { self.print_associated_const(ti.ident, ti.generics, ty, default); @@ -944,7 +943,7 @@ impl<'a> State<'a> { self.ann.pre(self, AnnNode::SubItem(ii.hir_id())); self.hardbreak_if_not_bol(); self.maybe_print_comment(ii.span.lo()); - self.print_attrs_as_outer(self.attrs(ii.hir_id())); + self.print_attrs(self.attrs(ii.hir_id())); match ii.kind { hir::ImplItemKind::Const(ty, expr) => { @@ -1028,27 +1027,16 @@ impl<'a> State<'a> { } fn print_block(&mut self, blk: &hir::Block<'_>, cb: BoxMarker, ib: BoxMarker) { - self.print_block_with_attrs(blk, &[], cb, ib) + self.print_block_maybe_unclosed(blk, Some(cb), ib) } fn print_block_unclosed(&mut self, blk: &hir::Block<'_>, ib: BoxMarker) { - self.print_block_maybe_unclosed(blk, &[], None, ib) - } - - fn print_block_with_attrs( - &mut self, - blk: &hir::Block<'_>, - attrs: &[hir::Attribute], - cb: BoxMarker, - ib: BoxMarker, - ) { - self.print_block_maybe_unclosed(blk, attrs, Some(cb), ib) + self.print_block_maybe_unclosed(blk, None, ib) } fn print_block_maybe_unclosed( &mut self, blk: &hir::Block<'_>, - attrs: &[hir::Attribute], cb: Option, ib: BoxMarker, ) { @@ -1060,8 +1048,6 @@ impl<'a> State<'a> { self.ann.pre(self, AnnNode::Block(blk)); self.bopen(ib); - self.print_attrs_as_inner(attrs); - for st in blk.stmts { self.print_stmt(st); } @@ -1251,7 +1237,7 @@ impl<'a> State<'a> { fn print_expr_field(&mut self, field: &hir::ExprField<'_>) { let cb = self.cbox(INDENT_UNIT); - self.print_attrs_as_outer(self.attrs(field.hir_id)); + self.print_attrs(self.attrs(field.hir_id)); if !field.is_shorthand { self.print_ident(field.ident); self.word_space(":"); @@ -1349,6 +1335,10 @@ impl<'a> State<'a> { self.word_nbsp("raw"); self.print_mutability(mutability, true); } + hir::BorrowKind::Pin => { + self.word_nbsp("pin"); + self.print_mutability(mutability, true); + } } self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Prefix); } @@ -1451,7 +1441,7 @@ impl<'a> State<'a> { fn print_expr(&mut self, expr: &hir::Expr<'_>) { self.maybe_print_comment(expr.span.lo()); - self.print_attrs_as_outer(self.attrs(expr.hir_id)); + self.print_attrs(self.attrs(expr.hir_id)); let ib = self.ibox(INDENT_UNIT); self.ann.pre(self, AnnNode::Expr(expr)); match expr.kind { @@ -1517,7 +1507,7 @@ impl<'a> State<'a> { self.bopen(ib); // Print `let _t = $init;`: - let temp = Ident::from_str("_t"); + let temp = Ident::with_dummy_span(sym::_t); self.print_local(false, Some(init), None, |this| this.print_ident(temp)); self.word(";"); @@ -2076,7 +2066,7 @@ impl<'a> State<'a> { self.space(); } let cb = self.cbox(INDENT_UNIT); - self.print_attrs_as_outer(self.attrs(field.hir_id)); + self.print_attrs(self.attrs(field.hir_id)); if !field.is_shorthand { self.print_ident(field.ident); self.word_nbsp(":"); @@ -2086,7 +2076,7 @@ impl<'a> State<'a> { } fn print_param(&mut self, arg: &hir::Param<'_>) { - self.print_attrs_as_outer(self.attrs(arg.hir_id)); + self.print_attrs(self.attrs(arg.hir_id)); self.print_pat(arg.pat); } @@ -2121,7 +2111,7 @@ impl<'a> State<'a> { let cb = self.cbox(INDENT_UNIT); self.ann.pre(self, AnnNode::Arm(arm)); let ib = self.ibox(0); - self.print_attrs_as_outer(self.attrs(arm.hir_id)); + self.print_attrs(self.attrs(arm.hir_id)); self.print_pat(arm.pat); self.space(); if let Some(ref g) = arm.guard { @@ -2409,7 +2399,7 @@ impl<'a> State<'a> { } fn print_where_predicate(&mut self, predicate: &hir::WherePredicate<'_>) { - self.print_attrs_as_outer(self.attrs(predicate.hir_id)); + self.print_attrs(self.attrs(predicate.hir_id)); match *predicate.kind { hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { bound_generic_params, diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index ac7ff65528d9..c21b16c9f9f0 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -1,6 +1,6 @@ -hir_typeck_abi_custom_call = - functions with the `"custom"` ABI cannot be called - .note = an `extern "custom"` function can only be called from within inline assembly +hir_typeck_abi_cannot_be_called = + functions with the {$abi} ABI cannot be called + .note = an `extern {$abi}` function can only be called using inline assembly hir_typeck_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function @@ -79,6 +79,9 @@ hir_typeck_cast_unknown_pointer = cannot cast {$to -> .note = the type information given here is insufficient to check whether the pointer cast is valid .label_from = the type information given here is insufficient to check whether the pointer cast is valid +hir_typeck_const_continue_bad_label = + `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]` + hir_typeck_const_select_must_be_const = this argument must be a `const fn` .help = consult the documentation on `const_eval_select` for more information diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 80bff09d0a43..f790c51f8f19 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -1,6 +1,6 @@ use std::iter; -use rustc_abi::ExternAbi; +use rustc_abi::{CanonAbi, ExternAbi}; use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey}; use rustc_hir::def::{self, CtorKind, Namespace, Res}; @@ -16,6 +16,7 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::LocalDefId; use rustc_span::{Span, sym}; +use rustc_target::spec::{AbiMap, AbiMapping}; use rustc_trait_selection::error_reporting::traits::DefIdOrName; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; @@ -84,7 +85,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { while result.is_none() && autoderef.next().is_some() { result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef); } - self.check_call_custom_abi(autoderef.final_ty(false), call_expr.span); + + match autoderef.final_ty(false).kind() { + ty::FnDef(def_id, _) => { + let abi = self.tcx.fn_sig(def_id).skip_binder().skip_binder().abi; + self.check_call_abi(abi, call_expr.span); + } + ty::FnPtr(_, header) => { + self.check_call_abi(header.abi, call_expr.span); + } + _ => { /* cannot have a non-rust abi */ } + } + self.register_predicates(autoderef.into_obligations()); let output = match result { @@ -137,19 +149,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { output } - /// Functions of type `extern "custom" fn(/* ... */)` cannot be called using `ExprKind::Call`. + /// Can a function with this ABI be called with a rust call expression? /// - /// These functions have a calling convention that is unknown to rust, hence it cannot generate - /// code for the call. The only way to execute such a function is via inline assembly. - fn check_call_custom_abi(&self, callee_ty: Ty<'tcx>, span: Span) { - let abi = match callee_ty.kind() { - ty::FnDef(def_id, _) => self.tcx.fn_sig(def_id).skip_binder().skip_binder().abi, - ty::FnPtr(_, header) => header.abi, - _ => return, + /// Some ABIs cannot be called from rust, either because rust does not know how to generate + /// code for the call, or because a call does not semantically make sense. + pub(crate) fn check_call_abi(&self, abi: ExternAbi, span: Span) { + let canon_abi = match AbiMap::from_target(&self.sess().target).canonize_abi(abi, false) { + AbiMapping::Direct(canon_abi) | AbiMapping::Deprecated(canon_abi) => canon_abi, + AbiMapping::Invalid => { + // This should be reported elsewhere, but we want to taint this body + // so that we don't try to evaluate calls to ABIs that are invalid. + let guar = self.dcx().span_delayed_bug( + span, + format!("invalid abi for platform should have reported an error: {abi}"), + ); + self.set_tainted_by_errors(guar); + return; + } }; - if let ExternAbi::Custom = abi { - self.tcx.dcx().emit_err(errors::AbiCustomCall { span }); + let valid = match canon_abi { + // Rust doesn't know how to call functions with this ABI. + CanonAbi::Custom => false, + + // These is an entry point for the host, and cannot be called on the GPU. + CanonAbi::GpuKernel => false, + + // The interrupt ABIs should only be called by the CPU. They have complex + // pre- and postconditions, and can use non-standard instructions like `iret` on x86. + CanonAbi::Interrupt(_) => false, + + CanonAbi::C + | CanonAbi::Rust + | CanonAbi::RustCold + | CanonAbi::Arm(_) + | CanonAbi::X86(_) => true, + }; + + if !valid { + let err = crate::errors::AbiCannotBeCalled { span, abi }; + self.tcx.dcx().emit_err(err); } } diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 24092c01125f..0ce0bc313c77 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -46,7 +46,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::infer::relate::RelateResult; use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; use rustc_infer::traits::{ - IfExpressionCause, MatchExpressionArmCause, Obligation, PredicateObligation, + IfExpressionCause, ImplSource, MatchExpressionArmCause, Obligation, PredicateObligation, PredicateObligations, SelectionError, }; use rustc_middle::span_bug; @@ -704,6 +704,19 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // be silent, as it causes a type mismatch later. } + Ok(Some(ImplSource::UserDefined(impl_source))) => { + queue.extend(impl_source.nested); + // Certain incoherent `CoerceUnsized` implementations may cause ICEs, + // so check the impl's validity. Taint the body so that we don't try + // to evaluate these invalid coercions in CTFE. We only need to do this + // for local impls, since upstream impls should be valid. + if impl_source.impl_def_id.is_local() + && let Err(guar) = + self.tcx.ensure_ok().coerce_unsized_info(impl_source.impl_def_id) + { + self.fcx.set_tainted_by_errors(guar); + } + } Ok(Some(impl_source)) => queue.extend(impl_source.nested_obligations()), } } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 5b55fbe91500..e5684f8cbe66 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1110,27 +1110,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - // Returns whether the given expression is a destruct assignment desugaring. - // For example, `(a, b) = (1, &2);` - // Here we try to find the pattern binding of the expression, - // `default_binding_modes` is false only for destruct assignment desugaring. + /// Returns whether the given expression is a destruct assignment desugaring. + /// For example, `(a, b) = (1, &2);` + /// Here we try to find the pattern binding of the expression, + /// `default_binding_modes` is false only for destruct assignment desugaring. pub(crate) fn is_destruct_assignment_desugaring(&self, expr: &hir::Expr<'_>) -> bool { if let hir::ExprKind::Path(hir::QPath::Resolved( _, hir::Path { res: hir::def::Res::Local(bind_hir_id), .. }, )) = expr.kind - { - let bind = self.tcx.hir_node(*bind_hir_id); - let parent = self.tcx.parent_hir_node(*bind_hir_id); - if let hir::Node::Pat(hir::Pat { + && let bind = self.tcx.hir_node(*bind_hir_id) + && let parent = self.tcx.parent_hir_node(*bind_hir_id) + && let hir::Node::Pat(hir::Pat { kind: hir::PatKind::Binding(_, _hir_id, _, _), .. }) = bind - && let hir::Node::Pat(hir::Pat { default_binding_modes: false, .. }) = parent - { - return true; - } + && let hir::Node::Pat(hir::Pat { default_binding_modes: false, .. }) = parent + { + true + } else { + false } - false } fn explain_self_literal( diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index abb8cdc1cdf3..3606c778fc40 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; +use rustc_abi::ExternAbi; use rustc_ast::Label; use rustc_errors::codes::*; use rustc_errors::{ @@ -30,8 +31,6 @@ pub(crate) struct BaseExpressionDoubleDot { )] pub default_field_values_suggestion: Option, #[subdiagnostic] - pub default_field_values_help: Option, - #[subdiagnostic] pub add_expr: Option, #[subdiagnostic] pub remove_dots: Option, @@ -61,10 +60,6 @@ pub(crate) struct BaseExpressionDoubleDotAddExpr { pub span: Span, } -#[derive(Subdiagnostic)] -#[help(hir_typeck_base_expression_double_dot_enable_default_field_values)] -pub(crate) struct BaseExpressionDoubleDotEnableDefaultFieldValues; - #[derive(Diagnostic)] #[diag(hir_typeck_field_multiply_specified_in_initializer, code = E0062)] pub(crate) struct FieldMultiplySpecifiedInInitializer { @@ -1165,8 +1160,17 @@ pub(crate) struct NakedFunctionsMustNakedAsm { } #[derive(Diagnostic)] -#[diag(hir_typeck_abi_custom_call)] -pub(crate) struct AbiCustomCall { +#[diag(hir_typeck_abi_cannot_be_called)] +pub(crate) struct AbiCannotBeCalled { + #[primary_span] + #[note] + pub span: Span, + pub abi: ExternAbi, +} + +#[derive(Diagnostic)] +#[diag(hir_typeck_const_continue_bad_label)] +pub(crate) struct ConstContinueBadLabel { #[primary_span] pub span: Span, } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 55c39d960e7c..2bc9dadb6653 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -5,8 +5,9 @@ //! //! See [`rustc_hir_analysis::check`] for more context on type checking in general. -use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx}; +use rustc_abi::{FIRST_VARIANT, FieldIdx}; use rustc_ast::util::parser::ExprPrecedence; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::unord::UnordMap; @@ -18,7 +19,7 @@ use rustc_errors::{ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_hir::{Attribute, ExprKind, HirId, QPath}; +use rustc_hir::{ExprKind, HirId, QPath}; use rustc_hir_analysis::NoVariantNamed; use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _}; use rustc_infer::infer; @@ -43,10 +44,9 @@ use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectatio use crate::coercion::{CoerceMany, DynamicCoerceMany}; use crate::errors::{ AddressOfTemporaryTaken, BaseExpressionDoubleDot, BaseExpressionDoubleDotAddExpr, - BaseExpressionDoubleDotEnableDefaultFieldValues, BaseExpressionDoubleDotRemove, - CantDereference, FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, - HelpUseLatestEdition, NakedAsmOutsideNakedFn, NoFieldOnType, NoFieldOnVariant, - ReturnLikeStatementKind, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive, + BaseExpressionDoubleDotRemove, CantDereference, FieldMultiplySpecifiedInInitializer, + FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition, NakedAsmOutsideNakedFn, NoFieldOnType, + NoFieldOnVariant, ReturnLikeStatementKind, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive, TypeMismatchFruTypo, YieldExprOutsideOfCoroutine, }; use crate::{ @@ -56,7 +56,7 @@ use crate::{ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence { - let for_each_attr = |id: HirId, callback: &mut dyn FnMut(&Attribute)| { + let has_attr = |id: HirId| -> bool { for attr in self.tcx.hir_attrs(id) { // For the purpose of rendering suggestions, disregard attributes // that originate from desugaring of any kind. For example, `x?` @@ -72,11 +72,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // let y: u32 = (x?).try_into().unwrap(); // + +++++++++++++++++++++ if attr.span().desugaring_kind().is_none() { - callback(attr); + return true; } } + false }; - expr.precedence(&for_each_attr) + expr.precedence(&has_attr) } /// Check an expr with an expectation type, and also demand that the expr's @@ -689,7 +690,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_named_place_expr(oprnd); Ty::new_ptr(self.tcx, ty, mutbl) } - hir::BorrowKind::Ref => { + hir::BorrowKind::Ref | hir::BorrowKind::Pin => { // Note: at this point, we cannot say what the best lifetime // is to use for resulting pointer. We want to use the // shortest lifetime possible so as to avoid spurious borrowck @@ -705,7 +706,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // whose address was taken can actually be made to live as long // as it needs to live. let region = self.next_region_var(infer::BorrowRegion(expr.span)); - Ty::new_ref(self.tcx, region, ty, mutbl) + match kind { + hir::BorrowKind::Ref => Ty::new_ref(self.tcx, region, ty, mutbl), + hir::BorrowKind::Pin => Ty::new_pinned_ref(self.tcx, region, ty, mutbl), + _ => unreachable!(), + } } } } @@ -1651,13 +1656,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(method.def_id), ); - // Functions of type `extern "custom" fn(/* ... */)` cannot be called using - // `ExprKind::MethodCall`. These functions have a calling convention that is - // unknown to rust, hence it cannot generate code for the call. The only way - // to execute such a function is via inline assembly. - if let ExternAbi::Custom = method.sig.abi { - self.tcx.dcx().emit_err(crate::errors::AbiCustomCall { span: expr.span }); - } + self.check_call_abi(method.sig.abi, expr.span); method.sig.output() } @@ -2158,7 +2157,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } if !self.tcx.features().default_field_values() { - let sugg = self.tcx.crate_level_attribute_injection_span(expr.hir_id); + let sugg = self.tcx.crate_level_attribute_injection_span(); self.dcx().emit_err(BaseExpressionDoubleDot { span: span.shrink_to_hi(), // We only mention enabling the feature if this is a nightly rustc *and* the @@ -2166,18 +2165,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { default_field_values_suggestion: if self.tcx.sess.is_nightly_build() && missing_mandatory_fields.is_empty() && !missing_optional_fields.is_empty() - && sugg.is_some() { - sugg - } else { - None - }, - default_field_values_help: if self.tcx.sess.is_nightly_build() - && missing_mandatory_fields.is_empty() - && !missing_optional_fields.is_empty() - && sugg.is_none() - { - Some(BaseExpressionDoubleDotEnableDefaultFieldValues) + Some(sugg) } else { None }, @@ -3795,7 +3784,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>, span: Span) -> Ty<'tcx> { if let rustc_ast::AsmMacro::NakedAsm = asm.asm_macro { - if !self.tcx.has_attr(self.body_id, sym::naked) { + if !find_attr!(self.tcx.get_all_attrs(self.body_id), AttributeKind::Naked(..)) { self.tcx.dcx().emit_err(NakedAsmOutsideNakedFn { span }); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index e979798a4029..8c18642e54a1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -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, + ) -> (Vec, Vec>) { + 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, diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 043a687914b7..1cc618e2aeec 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -42,6 +42,7 @@ mod writeback; pub use coercion::can_coerce; use fn_ctxt::FnCtxt; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; @@ -55,8 +56,8 @@ use rustc_middle::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config; +use rustc_span::Span; use rustc_span::def_id::LocalDefId; -use rustc_span::{Span, sym}; use tracing::{debug, instrument}; use typeck_root_ctxt::TypeckRootCtxt; @@ -173,7 +174,7 @@ fn typeck_with_inspect<'tcx>( .map(|(idx, ty)| fcx.normalize(arg_span(idx), ty)), ); - if tcx.has_attr(def_id, sym::naked) { + if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Naked(..)) { naked_functions::typeck_naked_fn(tcx, def_id, body); } diff --git a/compiler/rustc_hir_typeck/src/loops.rs b/compiler/rustc_hir_typeck/src/loops.rs index b06e0704b6ff..80eab578f134 100644 --- a/compiler/rustc_hir_typeck/src/loops.rs +++ b/compiler/rustc_hir_typeck/src/loops.rs @@ -2,6 +2,8 @@ use std::collections::BTreeMap; use std::fmt; use Context::*; +use rustc_ast::Label; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; @@ -14,8 +16,9 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::{BytePos, Span}; use crate::errors::{ - BreakInsideClosure, BreakInsideCoroutine, BreakNonLoop, ContinueLabeledBlock, OutsideLoop, - OutsideLoopSuggestion, UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock, + BreakInsideClosure, BreakInsideCoroutine, BreakNonLoop, ConstContinueBadLabel, + ContinueLabeledBlock, OutsideLoop, OutsideLoopSuggestion, UnlabeledCfInWhileCondition, + UnlabeledInLabeledBlock, }; /// The context in which a block is encountered. @@ -37,6 +40,11 @@ enum Context { AnonConst, /// E.g. `const { ... }`. ConstBlock, + /// E.g. `#[loop_match] loop { state = 'label: { /* ... */ } }`. + LoopMatch { + /// The label of the labeled block (not of the loop itself). + labeled_block: Label, + }, } #[derive(Clone)] @@ -141,7 +149,12 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> { } } hir::ExprKind::Loop(ref b, _, source, _) => { - self.with_context(Loop(source), |v| v.visit_block(b)); + let cx = match self.is_loop_match(e, b) { + Some(labeled_block) => LoopMatch { labeled_block }, + None => Loop(source), + }; + + self.with_context(cx, |v| v.visit_block(b)); } hir::ExprKind::Closure(&hir::Closure { ref fn_decl, body, fn_decl_span, kind, .. @@ -197,6 +210,23 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> { Err(hir::LoopIdError::UnresolvedLabel) => None, }; + // A `#[const_continue]` must break to a block in a `#[loop_match]`. + if find_attr!(self.tcx.hir_attrs(e.hir_id), AttributeKind::ConstContinue(_)) { + if let Some(break_label) = break_label.label { + let is_target_label = |cx: &Context| match cx { + Context::LoopMatch { labeled_block } => { + break_label.ident.name == labeled_block.ident.name + } + _ => false, + }; + + if !self.cx_stack.iter().rev().any(is_target_label) { + let span = break_label.ident.span; + self.tcx.dcx().emit_fatal(ConstContinueBadLabel { span }); + } + } + } + if let Some(Node::Block(_)) = loop_id.map(|id| self.tcx.hir_node(id)) { return; } @@ -299,7 +329,7 @@ impl<'hir> CheckLoopVisitor<'hir> { cx_pos: usize, ) { match self.cx_stack[cx_pos] { - LabeledBlock | Loop(_) => {} + LabeledBlock | Loop(_) | LoopMatch { .. } => {} Closure(closure_span) => { self.tcx.dcx().emit_err(BreakInsideClosure { span, @@ -380,4 +410,36 @@ impl<'hir> CheckLoopVisitor<'hir> { }); } } + + /// Is this a loop annotated with `#[loop_match]` that looks syntactically sound? + fn is_loop_match( + &self, + e: &'hir hir::Expr<'hir>, + body: &'hir hir::Block<'hir>, + ) -> Option
  • {crate_name}
  • ", trailing_slash = ensure_trailing_slash(crate_name), ); - ret.push(path.clone(), part); + ret.push(path.to_path_buf(), part); } Ok(ret) } @@ -737,7 +733,7 @@ impl TraitAliasPart { }, }; - let implementors = imps + let mut implementors = imps .iter() .filter_map(|imp| { // If the trait and implementation are in the same crate, then @@ -759,12 +755,12 @@ impl TraitAliasPart { }) } }) - .collect::>(); + .peekable(); // Only create a js file if we have impls to add to it. If the trait is // documented locally though we always create the file to avoid dead // links. - if implementors.is_empty() && !cache.paths.contains_key(&did) { + if implementors.peek().is_none() && !cache.paths.contains_key(&did) { continue; } @@ -775,11 +771,7 @@ impl TraitAliasPart { path.push(format!("{remote_item_type}.{}.js", remote_path[remote_path.len() - 1])); let part = OrderedJson::array_sorted( - implementors - .iter() - .map(OrderedJson::serialize) - .collect::, _>>() - .unwrap(), + implementors.map(|implementor| OrderedJson::serialize(implementor).unwrap()), ); path_parts.push(path, OrderedJson::array_unsorted([crate_name_json, &part])); } @@ -874,9 +866,8 @@ impl<'item> DocVisitor<'item> for TypeImplCollector<'_, '_, 'item> { let impl_ = cache .impls .get(&target_did) - .map(|v| &v[..]) - .unwrap_or_default() - .iter() + .into_iter() + .flatten() .map(|impl_| { (impl_.impl_item.item_id, AliasedTypeImpl { impl_, type_aliases: Vec::new() }) }) @@ -891,14 +882,8 @@ impl<'item> DocVisitor<'item> for TypeImplCollector<'_, '_, 'item> { // Exclude impls that are directly on this type. They're already in the HTML. // Some inlining scenarios can cause there to be two versions of the same // impl: one on the type alias and one on the underlying target type. - let mut seen_impls: FxHashSet = cache - .impls - .get(&self_did) - .map(|s| &s[..]) - .unwrap_or_default() - .iter() - .map(|i| i.impl_item.item_id) - .collect(); + let mut seen_impls: FxHashSet = + cache.impls.get(&self_did).into_iter().flatten().map(|i| i.impl_item.item_id).collect(); for (impl_item_id, aliased_type_impl) in &mut aliased_type.impl_ { // Only include this impl if it actually unifies with this alias. // Synthetic impls are not included; those are also included in the HTML. diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 1fa6b5a60f3a..c34b31542697 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -353,7 +353,7 @@ pub(crate) fn print_src( ); Ok(()) }); - let max_nb_digits = if lines > 0 { lines.ilog(10) + 1 } else { 1 }; + let max_nb_digits = if lines > 0 { lines.ilog10() + 1 } else { 1 }; match source_context { SourceContext::Standalone { file_path } => Source { code_html: code, diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 7b1a61a3ffa4..2de8f836da3b 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1,6 +1,6 @@ // Local js definitions: /* global addClass, getSettingValue, hasClass, updateLocalStorage */ -/* global onEachLazy, removeClass, getVar */ +/* global onEachLazy, removeClass, getVar, nonnull */ "use strict"; @@ -2138,3 +2138,31 @@ function preLoadCss(cssUrl) { elem.addEventListener("click", showHideCodeExampleButtons); }); }()); + +// This section is a bugfix for firefox: when copying text with `user-select: none`, it adds +// extra backline characters. +// +// Rustdoc issue: Workaround for https://github.com/rust-lang/rust/issues/141464 +// Firefox issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1273836 +(function() { + document.body.addEventListener("copy", event => { + let target = nonnull(event.target); + let isInsideCode = false; + while (target && target !== document.body) { + // @ts-expect-error + if (target.tagName === "CODE") { + isInsideCode = true; + break; + } + // @ts-expect-error + target = target.parentElement; + } + if (!isInsideCode) { + return; + } + const selection = document.getSelection(); + // @ts-expect-error + nonnull(event.clipboardData).setData("text/plain", selection.toString()); + event.preventDefault(); + }); +}()); diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index b611a3e501dc..a2c48708512e 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -5394,43 +5394,6 @@ function updateCrate(ev) { search(true); } -// @ts-expect-error -function initSearch(searchIndx) { - rawSearchIndex = searchIndx; - if (typeof window !== "undefined") { - // @ts-expect-error - docSearch = new DocSearch(rawSearchIndex, ROOT_PATH, searchState); - registerSearchEvents(); - // If there's a search term in the URL, execute the search now. - if (window.searchState.getQueryStringParams().search) { - search(); - } - } else if (typeof exports !== "undefined") { - // @ts-expect-error - docSearch = new DocSearch(rawSearchIndex, ROOT_PATH, searchState); - exports.docSearch = docSearch; - exports.parseQuery = DocSearch.parseQuery; - } -} - -if (typeof exports !== "undefined") { - exports.initSearch = initSearch; -} - -if (typeof window !== "undefined") { - // @ts-expect-error - window.initSearch = initSearch; - // @ts-expect-error - if (window.searchIndex !== undefined) { - // @ts-expect-error - initSearch(window.searchIndex); - } -} else { - // Running in Node, not a browser. Run initSearch just to produce the - // exports. - initSearch(new Map()); -} - // Parts of this code are based on Lucene, which is licensed under the // Apache/2.0 license. // More information found here: @@ -5909,3 +5872,44 @@ Lev1TParametricDescription.prototype.toStates3 = /*3 bits per value */ new Int32 Lev1TParametricDescription.prototype.offsetIncrs3 = /*2 bits per value */ new Int32Array([ 0xa0fc0000,0x5555ba08,0x55555555, ]); + +// ==================== +// WARNING: Nothing should be added below this comment: we need the `initSearch` function to +// be called ONLY when the whole file has been parsed and loaded. + +// @ts-expect-error +function initSearch(searchIndx) { + rawSearchIndex = searchIndx; + if (typeof window !== "undefined") { + // @ts-expect-error + docSearch = new DocSearch(rawSearchIndex, ROOT_PATH, searchState); + registerSearchEvents(); + // If there's a search term in the URL, execute the search now. + if (window.searchState.getQueryStringParams().search) { + search(); + } + } else if (typeof exports !== "undefined") { + // @ts-expect-error + docSearch = new DocSearch(rawSearchIndex, ROOT_PATH, searchState); + exports.docSearch = docSearch; + exports.parseQuery = DocSearch.parseQuery; + } +} + +if (typeof exports !== "undefined") { + exports.initSearch = initSearch; +} + +if (typeof window !== "undefined") { + // @ts-expect-error + window.initSearch = initSearch; + // @ts-expect-error + if (window.searchIndex !== undefined) { + // @ts-expect-error + initSearch(window.searchIndex); + } +} else { + // Running in Node, not a browser. Run initSearch just to produce the + // exports. + initSearch(new Map()); +} diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 6bdf3b5fe387..f51b35097f66 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -11,12 +11,11 @@ use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; use rustc_metadata::rendered_const; use rustc_middle::{bug, ty}; -use rustc_span::{Pos, Symbol, kw}; +use rustc_span::{Pos, kw, sym}; use rustdoc_json_types::*; use thin_vec::ThinVec; use crate::clean::{self, ItemId}; -use crate::formats::FormatRenderer; use crate::formats::item_type::ItemType; use crate::json::JsonRenderer; use crate::passes::collect_intra_doc_links::UrlFragment; @@ -41,7 +40,7 @@ impl JsonRenderer<'_> { }) .collect(); let docs = item.opt_doc_value(); - let attrs = item.attributes_and_repr(self.tcx, self.cache(), true); + let attrs = item.attributes(self.tcx, &self.cache, true); let span = item.span(self.tcx); let visibility = item.visibility(self.tcx); let clean::ItemInner { name, item_id, .. } = *item.inner; @@ -67,47 +66,16 @@ impl JsonRenderer<'_> { id, crate_id: item_id.krate().as_u32(), name: name.map(|sym| sym.to_string()), - span: span.and_then(|span| self.convert_span(span)), - visibility: self.convert_visibility(visibility), + span: span.and_then(|span| span.into_json(self)), + visibility: visibility.into_json(self), docs, attrs, - deprecation: deprecation.map(from_deprecation), + deprecation: deprecation.into_json(self), inner, links, }) } - fn convert_span(&self, span: clean::Span) -> Option { - match span.filename(self.sess()) { - rustc_span::FileName::Real(name) => { - if let Some(local_path) = name.into_local_path() { - let hi = span.hi(self.sess()); - let lo = span.lo(self.sess()); - Some(Span { - filename: local_path, - begin: (lo.line, lo.col.to_usize() + 1), - end: (hi.line, hi.col.to_usize() + 1), - }) - } else { - None - } - } - _ => None, - } - } - - fn convert_visibility(&self, v: Option>) -> Visibility { - match v { - None => Visibility::Default, - Some(ty::Visibility::Public) => Visibility::Public, - Some(ty::Visibility::Restricted(did)) if did.is_crate_root() => Visibility::Crate, - Some(ty::Visibility::Restricted(did)) => Visibility::Restricted { - parent: self.id_from_item_default(did.into()), - path: self.tcx.def_path(did).to_string_no_crate_verbose(), - }, - } - } - fn ids(&self, items: &[clean::Item]) -> Vec { items .iter() @@ -141,11 +109,29 @@ where } } +impl FromClean> for U +where + U: FromClean, +{ + fn from_clean(opt: &Box, renderer: &JsonRenderer<'_>) -> Self { + opt.as_ref().into_json(renderer) + } +} + +impl FromClean> for Option +where + U: FromClean, +{ + fn from_clean(opt: &Option, renderer: &JsonRenderer<'_>) -> Self { + opt.as_ref().map(|x| x.into_json(renderer)) + } +} + impl FromClean> for Vec where U: FromClean, { - fn from_clean(items: &Vec, renderer: &JsonRenderer<'_>) -> Vec { + fn from_clean(items: &Vec, renderer: &JsonRenderer<'_>) -> Self { items.iter().map(|i| i.into_json(renderer)).collect() } } @@ -154,35 +140,78 @@ impl FromClean> for Vec where U: FromClean, { - fn from_clean(items: &ThinVec, renderer: &JsonRenderer<'_>) -> Vec { + fn from_clean(items: &ThinVec, renderer: &JsonRenderer<'_>) -> Self { items.iter().map(|i| i.into_json(renderer)).collect() } } -pub(crate) fn from_deprecation(deprecation: attrs::Deprecation) -> Deprecation { - let attrs::Deprecation { since, note, suggestion: _ } = deprecation; - let since = match since { - DeprecatedSince::RustcVersion(version) => Some(version.to_string()), - DeprecatedSince::Future => Some("TBD".to_owned()), - DeprecatedSince::NonStandard(since) => Some(since.to_string()), - DeprecatedSince::Unspecified | DeprecatedSince::Err => None, - }; - Deprecation { since, note: note.map(|s| s.to_string()) } +impl FromClean for Option { + fn from_clean(span: &clean::Span, renderer: &JsonRenderer<'_>) -> Self { + match span.filename(renderer.sess()) { + rustc_span::FileName::Real(name) => { + if let Some(local_path) = name.into_local_path() { + let hi = span.hi(renderer.sess()); + let lo = span.lo(renderer.sess()); + Some(Span { + filename: local_path, + begin: (lo.line, lo.col.to_usize() + 1), + end: (hi.line, hi.col.to_usize() + 1), + }) + } else { + None + } + } + _ => None, + } + } } -impl FromClean for GenericArgs { - fn from_clean(args: &clean::GenericArgs, renderer: &JsonRenderer<'_>) -> Self { +impl FromClean>> for Visibility { + fn from_clean(v: &Option>, renderer: &JsonRenderer<'_>) -> Self { + match v { + None => Visibility::Default, + Some(ty::Visibility::Public) => Visibility::Public, + Some(ty::Visibility::Restricted(did)) if did.is_crate_root() => Visibility::Crate, + Some(ty::Visibility::Restricted(did)) => Visibility::Restricted { + parent: renderer.id_from_item_default((*did).into()), + path: renderer.tcx.def_path(*did).to_string_no_crate_verbose(), + }, + } + } +} + +impl FromClean for Deprecation { + fn from_clean(deprecation: &attrs::Deprecation, _renderer: &JsonRenderer<'_>) -> Self { + let attrs::Deprecation { since, note, suggestion: _ } = deprecation; + let since = match since { + DeprecatedSince::RustcVersion(version) => Some(version.to_string()), + DeprecatedSince::Future => Some("TBD".to_string()), + DeprecatedSince::NonStandard(since) => Some(since.to_string()), + DeprecatedSince::Unspecified | DeprecatedSince::Err => None, + }; + Deprecation { since, note: note.map(|sym| sym.to_string()) } + } +} + +impl FromClean for Option> { + fn from_clean(generic_args: &clean::GenericArgs, renderer: &JsonRenderer<'_>) -> Self { use clean::GenericArgs::*; - match args { - AngleBracketed { args, constraints } => GenericArgs::AngleBracketed { - args: args.into_json(renderer), - constraints: constraints.into_json(renderer), - }, - Parenthesized { inputs, output } => GenericArgs::Parenthesized { + match generic_args { + AngleBracketed { args, constraints } => { + if generic_args.is_empty() { + None + } else { + Some(Box::new(GenericArgs::AngleBracketed { + args: args.into_json(renderer), + constraints: constraints.into_json(renderer), + })) + } + } + Parenthesized { inputs, output } => Some(Box::new(GenericArgs::Parenthesized { inputs: inputs.into_json(renderer), - output: output.as_ref().map(|a| a.as_ref().into_json(renderer)), - }, - ReturnTypeNotation => GenericArgs::ReturnTypeNotation, + output: output.into_json(renderer), + })), + ReturnTypeNotation => Some(Box::new(GenericArgs::ReturnTypeNotation)), } } } @@ -191,7 +220,7 @@ impl FromClean for GenericArg { fn from_clean(arg: &clean::GenericArg, renderer: &JsonRenderer<'_>) -> Self { use clean::GenericArg::*; match arg { - Lifetime(l) => GenericArg::Lifetime(convert_lifetime(l)), + Lifetime(l) => GenericArg::Lifetime(l.into_json(renderer)), Type(t) => GenericArg::Type(t.into_json(renderer)), Const(box c) => GenericArg::Const(c.into_json(renderer)), Infer => GenericArg::Infer, @@ -199,17 +228,6 @@ impl FromClean for GenericArg { } } -impl FromClean for Constant { - // FIXME(generic_const_items): Add support for generic const items. - fn from_clean(constant: &clean::Constant, renderer: &JsonRenderer<'_>) -> Self { - let tcx = renderer.tcx; - let expr = constant.expr(tcx); - let value = constant.value(tcx); - let is_literal = constant.is_literal(tcx); - Constant { expr, value, is_literal } - } -} - impl FromClean for Constant { // FIXME(generic_const_items): Add support for generic const items. fn from_clean(constant: &clean::ConstantKind, renderer: &JsonRenderer<'_>) -> Self { @@ -257,21 +275,25 @@ fn from_clean_item(item: &clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum StructFieldItem(f) => ItemEnum::StructField(f.into_json(renderer)), EnumItem(e) => ItemEnum::Enum(e.into_json(renderer)), VariantItem(v) => ItemEnum::Variant(v.into_json(renderer)), - FunctionItem(f) => ItemEnum::Function(from_function(f, true, header.unwrap(), renderer)), + FunctionItem(f) => { + ItemEnum::Function(from_clean_function(f, true, header.unwrap(), renderer)) + } ForeignFunctionItem(f, _) => { - ItemEnum::Function(from_function(f, false, header.unwrap(), renderer)) + ItemEnum::Function(from_clean_function(f, false, header.unwrap(), renderer)) } - TraitItem(t) => ItemEnum::Trait(t.as_ref().into_json(renderer)), + TraitItem(t) => ItemEnum::Trait(t.into_json(renderer)), TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_json(renderer)), - MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), renderer)), - RequiredMethodItem(m) => { - ItemEnum::Function(from_function(m, false, header.unwrap(), renderer)) + MethodItem(m, _) => { + ItemEnum::Function(from_clean_function(m, true, header.unwrap(), renderer)) } - ImplItem(i) => ItemEnum::Impl(i.as_ref().into_json(renderer)), - StaticItem(s) => ItemEnum::Static(convert_static(s, &rustc_hir::Safety::Safe, renderer)), - ForeignStaticItem(s, safety) => ItemEnum::Static(convert_static(s, safety, renderer)), + RequiredMethodItem(m) => { + ItemEnum::Function(from_clean_function(m, false, header.unwrap(), renderer)) + } + ImplItem(i) => ItemEnum::Impl(i.into_json(renderer)), + StaticItem(s) => ItemEnum::Static(from_clean_static(s, rustc_hir::Safety::Safe, renderer)), + ForeignStaticItem(s, safety) => ItemEnum::Static(from_clean_static(s, *safety, renderer)), ForeignTypeItem => ItemEnum::ExternType, - TypeAliasItem(t) => ItemEnum::TypeAlias(t.as_ref().into_json(renderer)), + TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_json(renderer)), // FIXME(generic_const_items): Add support for generic free consts ConstantItem(ci) => ItemEnum::Constant { type_: ci.type_.into_json(renderer), @@ -287,7 +309,7 @@ fn from_clean_item(item: &clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum } // FIXME(generic_const_items): Add support for generic associated consts. RequiredAssocConstItem(_generics, ty) => { - ItemEnum::AssocConst { type_: ty.as_ref().into_json(renderer), value: None } + ItemEnum::AssocConst { type_: ty.into_json(renderer), value: None } } // FIXME(generic_const_items): Add support for generic associated consts. ProvidedAssocConstItem(ci) | ImplAssocConstItem(ci) => ItemEnum::AssocConst { @@ -359,32 +381,38 @@ impl FromClean for Union { } } -pub(crate) fn from_fn_header(header: &rustc_hir::FnHeader) -> FunctionHeader { - FunctionHeader { - is_async: header.is_async(), - is_const: header.is_const(), - is_unsafe: header.is_unsafe(), - abi: convert_abi(header.abi), +impl FromClean for FunctionHeader { + fn from_clean(header: &rustc_hir::FnHeader, renderer: &JsonRenderer<'_>) -> Self { + FunctionHeader { + is_async: header.is_async(), + is_const: header.is_const(), + is_unsafe: header.is_unsafe(), + abi: header.abi.into_json(renderer), + } } } -fn convert_abi(a: ExternAbi) -> Abi { - match a { - ExternAbi::Rust => Abi::Rust, - ExternAbi::C { unwind } => Abi::C { unwind }, - ExternAbi::Cdecl { unwind } => Abi::Cdecl { unwind }, - ExternAbi::Stdcall { unwind } => Abi::Stdcall { unwind }, - ExternAbi::Fastcall { unwind } => Abi::Fastcall { unwind }, - ExternAbi::Aapcs { unwind } => Abi::Aapcs { unwind }, - ExternAbi::Win64 { unwind } => Abi::Win64 { unwind }, - ExternAbi::SysV64 { unwind } => Abi::SysV64 { unwind }, - ExternAbi::System { unwind } => Abi::System { unwind }, - _ => Abi::Other(a.to_string()), +impl FromClean for Abi { + fn from_clean(a: &ExternAbi, _renderer: &JsonRenderer<'_>) -> Self { + match *a { + ExternAbi::Rust => Abi::Rust, + ExternAbi::C { unwind } => Abi::C { unwind }, + ExternAbi::Cdecl { unwind } => Abi::Cdecl { unwind }, + ExternAbi::Stdcall { unwind } => Abi::Stdcall { unwind }, + ExternAbi::Fastcall { unwind } => Abi::Fastcall { unwind }, + ExternAbi::Aapcs { unwind } => Abi::Aapcs { unwind }, + ExternAbi::Win64 { unwind } => Abi::Win64 { unwind }, + ExternAbi::SysV64 { unwind } => Abi::SysV64 { unwind }, + ExternAbi::System { unwind } => Abi::System { unwind }, + _ => Abi::Other(a.to_string()), + } } } -fn convert_lifetime(l: &clean::Lifetime) -> String { - l.0.to_string() +impl FromClean for String { + fn from_clean(l: &clean::Lifetime, _renderer: &JsonRenderer<'_>) -> String { + l.0.to_string() + } } impl FromClean for Generics { @@ -409,16 +437,16 @@ impl FromClean for GenericParamDefKind { fn from_clean(kind: &clean::GenericParamDefKind, renderer: &JsonRenderer<'_>) -> Self { use clean::GenericParamDefKind::*; match kind { - Lifetime { outlives } => GenericParamDefKind::Lifetime { - outlives: outlives.into_iter().map(convert_lifetime).collect(), - }, + Lifetime { outlives } => { + GenericParamDefKind::Lifetime { outlives: outlives.into_json(renderer) } + } Type { bounds, default, synthetic } => GenericParamDefKind::Type { bounds: bounds.into_json(renderer), - default: default.as_ref().map(|x| x.as_ref().into_json(renderer)), + default: default.into_json(renderer), is_synthetic: *synthetic, }, Const { ty, default, synthetic: _ } => GenericParamDefKind::Const { - type_: ty.as_ref().into_json(renderer), + type_: ty.into_json(renderer), default: default.as_ref().map(|x| x.as_ref().clone()), }, } @@ -432,45 +460,14 @@ impl FromClean for WherePredicate { BoundPredicate { ty, bounds, bound_params } => WherePredicate::BoundPredicate { type_: ty.into_json(renderer), bounds: bounds.into_json(renderer), - generic_params: bound_params - .iter() - .map(|x| { - let name = x.name.to_string(); - let kind = match &x.kind { - clean::GenericParamDefKind::Lifetime { outlives } => { - GenericParamDefKind::Lifetime { - outlives: outlives.iter().map(|lt| lt.0.to_string()).collect(), - } - } - clean::GenericParamDefKind::Type { bounds, default, synthetic } => { - GenericParamDefKind::Type { - bounds: bounds - .into_iter() - .map(|bound| bound.into_json(renderer)) - .collect(), - default: default - .as_ref() - .map(|ty| ty.as_ref().into_json(renderer)), - is_synthetic: *synthetic, - } - } - clean::GenericParamDefKind::Const { ty, default, synthetic: _ } => { - GenericParamDefKind::Const { - type_: ty.as_ref().into_json(renderer), - default: default.as_ref().map(|d| d.as_ref().clone()), - } - } - }; - GenericParamDef { name, kind } - }) - .collect(), + generic_params: bound_params.into_json(renderer), }, RegionPredicate { lifetime, bounds } => WherePredicate::LifetimePredicate { - lifetime: convert_lifetime(lifetime), + lifetime: lifetime.into_json(renderer), outlives: bounds .iter() .map(|bound| match bound { - clean::GenericBound::Outlives(lt) => convert_lifetime(lt), + clean::GenericBound::Outlives(lt) => lt.into_json(renderer), _ => bug!("found non-outlives-bound on lifetime predicate"), }) .collect(), @@ -494,15 +491,15 @@ impl FromClean for GenericBound { GenericBound::TraitBound { trait_: trait_.into_json(renderer), generic_params: generic_params.into_json(renderer), - modifier: from_trait_bound_modifier(modifier), + modifier: modifier.into_json(renderer), } } - Outlives(lifetime) => GenericBound::Outlives(convert_lifetime(lifetime)), + Outlives(lifetime) => GenericBound::Outlives(lifetime.into_json(renderer)), Use(args) => GenericBound::Use( args.iter() .map(|arg| match arg { clean::PreciseCapturingArg::Lifetime(lt) => { - PreciseCapturingArg::Lifetime(convert_lifetime(lt)) + PreciseCapturingArg::Lifetime(lt.into_json(renderer)) } clean::PreciseCapturingArg::Param(param) => { PreciseCapturingArg::Param(param.to_string()) @@ -514,19 +511,22 @@ impl FromClean for GenericBound { } } -pub(crate) fn from_trait_bound_modifier( - modifiers: &rustc_hir::TraitBoundModifiers, -) -> TraitBoundModifier { - use rustc_hir as hir; - let hir::TraitBoundModifiers { constness, polarity } = modifiers; - match (constness, polarity) { - (hir::BoundConstness::Never, hir::BoundPolarity::Positive) => TraitBoundModifier::None, - (hir::BoundConstness::Never, hir::BoundPolarity::Maybe(_)) => TraitBoundModifier::Maybe, - (hir::BoundConstness::Maybe(_), hir::BoundPolarity::Positive) => { - TraitBoundModifier::MaybeConst +impl FromClean for TraitBoundModifier { + fn from_clean( + modifiers: &rustc_hir::TraitBoundModifiers, + _renderer: &JsonRenderer<'_>, + ) -> Self { + use rustc_hir as hir; + let hir::TraitBoundModifiers { constness, polarity } = modifiers; + match (constness, polarity) { + (hir::BoundConstness::Never, hir::BoundPolarity::Positive) => TraitBoundModifier::None, + (hir::BoundConstness::Never, hir::BoundPolarity::Maybe(_)) => TraitBoundModifier::Maybe, + (hir::BoundConstness::Maybe(_), hir::BoundPolarity::Positive) => { + TraitBoundModifier::MaybeConst + } + // FIXME: Fill out the rest of this matrix. + _ => TraitBoundModifier::None, } - // FIXME: Fill out the rest of this matrix. - _ => TraitBoundModifier::None, } } @@ -540,35 +540,35 @@ impl FromClean for Type { match ty { clean::Type::Path { path } => Type::ResolvedPath(path.into_json(renderer)), clean::Type::DynTrait(bounds, lt) => Type::DynTrait(DynTrait { - lifetime: lt.as_ref().map(convert_lifetime), + lifetime: lt.into_json(renderer), traits: bounds.into_json(renderer), }), Generic(s) => Type::Generic(s.to_string()), // FIXME: add dedicated variant to json Type? SelfTy => Type::Generic("Self".to_owned()), Primitive(p) => Type::Primitive(p.as_sym().to_string()), - BareFunction(f) => Type::FunctionPointer(Box::new(f.as_ref().into_json(renderer))), + BareFunction(f) => Type::FunctionPointer(Box::new(f.into_json(renderer))), Tuple(t) => Type::Tuple(t.into_json(renderer)), - Slice(t) => Type::Slice(Box::new(t.as_ref().into_json(renderer))), + Slice(t) => Type::Slice(Box::new(t.into_json(renderer))), Array(t, s) => { - Type::Array { type_: Box::new(t.as_ref().into_json(renderer)), len: s.to_string() } + Type::Array { type_: Box::new(t.into_json(renderer)), len: s.to_string() } } clean::Type::Pat(t, p) => Type::Pat { - type_: Box::new(t.as_ref().into_json(renderer)), + type_: Box::new(t.into_json(renderer)), __pat_unstable_do_not_use: p.to_string(), }, ImplTrait(g) => Type::ImplTrait(g.into_json(renderer)), Infer => Type::Infer, RawPointer(mutability, type_) => Type::RawPointer { is_mutable: *mutability == ast::Mutability::Mut, - type_: Box::new(type_.as_ref().into_json(renderer)), + type_: Box::new(type_.into_json(renderer)), }, BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef { - lifetime: lifetime.as_ref().map(convert_lifetime), + lifetime: lifetime.into_json(renderer), is_mutable: *mutability == ast::Mutability::Mut, - type_: Box::new(type_.as_ref().into_json(renderer)), + type_: Box::new(type_.into_json(renderer)), }, - QPath(qpath) => qpath.as_ref().into_json(renderer), + QPath(qpath) => qpath.into_json(renderer), // FIXME(unsafe_binder): Implement rustdoc-json. UnsafeBinder(_) => todo!(), } @@ -576,11 +576,24 @@ impl FromClean for Type { } impl FromClean for Path { - fn from_clean(path: &clean::Path, renderer: &JsonRenderer<'_>) -> Path { + fn from_clean(path: &clean::Path, renderer: &JsonRenderer<'_>) -> Self { Path { path: path.whole_name(), id: renderer.id_from_item_default(path.def_id().into()), - args: path.segments.last().map(|args| Box::new(args.args.into_json(renderer))), + args: { + if let Some((final_seg, rest_segs)) = path.segments.split_last() { + // In general, `clean::Path` can hold things like + // `std::vec::Vec::::new`, where generic args appear + // in a middle segment. But for the places where `Path` is + // used by rustdoc-json-types, generic args can only be + // used in the final segment, e.g. `std::vec::Vec`. So + // check that the non-final segments have no generic args. + assert!(rest_segs.iter().all(|seg| seg.args.is_empty())); + final_seg.args.into_json(renderer) + } else { + None // no generics on any segments because there are no segments + } + }, } } } @@ -591,15 +604,15 @@ impl FromClean for Type { Self::QualifiedPath { name: assoc.name.to_string(), - args: Box::new(assoc.args.into_json(renderer)), + args: assoc.args.into_json(renderer), self_type: Box::new(self_type.into_json(renderer)), - trait_: trait_.as_ref().map(|trait_| trait_.into_json(renderer)), + trait_: trait_.into_json(renderer), } } } impl FromClean for Term { - fn from_clean(term: &clean::Term, renderer: &JsonRenderer<'_>) -> Term { + fn from_clean(term: &clean::Term, renderer: &JsonRenderer<'_>) -> Self { match term { clean::Term::Type(ty) => Term::Type(ty.into_json(renderer)), clean::Term::Constant(c) => Term::Constant(c.into_json(renderer)), @@ -615,7 +628,7 @@ impl FromClean for FunctionPointer { is_unsafe: safety.is_unsafe(), is_const: false, is_async: false, - abi: convert_abi(*abi), + abi: abi.into_json(renderer), }, generic_params: generic_params.into_json(renderer), sig: decl.into_json(renderer), @@ -694,17 +707,17 @@ impl FromClean for Impl { .into_iter() .map(|x| x.to_string()) .collect(), - trait_: trait_.as_ref().map(|path| path.into_json(renderer)), + trait_: trait_.into_json(renderer), for_: for_.into_json(renderer), items: renderer.ids(&items), is_negative, is_synthetic, - blanket_impl: blanket_impl.map(|x| x.as_ref().into_json(renderer)), + blanket_impl: blanket_impl.map(|x| x.into_json(renderer)), } } } -pub(crate) fn from_function( +pub(crate) fn from_clean_function( clean::Function { decl, generics }: &clean::Function, has_body: bool, header: rustc_hir::FnHeader, @@ -713,7 +726,7 @@ pub(crate) fn from_function( Function { sig: decl.into_json(renderer), generics: generics.into_json(renderer), - header: from_fn_header(&header), + header: header.into_json(renderer), has_body, } } @@ -735,7 +748,7 @@ impl FromClean for Variant { fn from_clean(variant: &clean::Variant, renderer: &JsonRenderer<'_>) -> Self { use clean::VariantKind::*; - let discriminant = variant.discriminant.as_ref().map(|d| d.into_json(renderer)); + let discriminant = variant.discriminant.into_json(renderer); let kind = match &variant.kind { CLike => VariantKind::Plain, @@ -768,10 +781,7 @@ impl FromClean for Use { use clean::ImportKind::*; let (name, is_glob) = match import.kind { Simple(s) => (s.to_string(), false), - Glob => ( - import.source.path.last_opt().unwrap_or_else(|| Symbol::intern("*")).to_string(), - true, - ), + Glob => (import.source.path.last_opt().unwrap_or(sym::asterisk).to_string(), true), }; Use { source: import.source.path.whole_name(), @@ -783,20 +793,22 @@ impl FromClean for Use { } impl FromClean for ProcMacro { - fn from_clean(mac: &clean::ProcMacro, _renderer: &JsonRenderer<'_>) -> Self { + fn from_clean(mac: &clean::ProcMacro, renderer: &JsonRenderer<'_>) -> Self { ProcMacro { - kind: from_macro_kind(mac.kind), + kind: mac.kind.into_json(renderer), helpers: mac.helpers.iter().map(|x| x.to_string()).collect(), } } } -pub(crate) fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind { - use rustc_span::hygiene::MacroKind::*; - match kind { - Bang => MacroKind::Bang, - Attr => MacroKind::Attr, - Derive => MacroKind::Derive, +impl FromClean for MacroKind { + fn from_clean(kind: &rustc_span::hygiene::MacroKind, _renderer: &JsonRenderer<'_>) -> Self { + use rustc_span::hygiene::MacroKind::*; + match kind { + Bang => MacroKind::Bang, + Attr => MacroKind::Attr, + Derive => MacroKind::Derive, + } } } @@ -807,9 +819,9 @@ impl FromClean for TypeAlias { } } -fn convert_static( +fn from_clean_static( stat: &clean::Static, - safety: &rustc_hir::Safety, + safety: rustc_hir::Safety, renderer: &JsonRenderer<'_>, ) -> Static { let tcx = renderer.tcx; diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 2feadce26d09..600a4b429f3c 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -18,7 +18,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use rustc_session::features::StabilityExt; use rustc_span::def_id::LOCAL_CRATE; use rustdoc_json_types as types; // It's important to use the FxHashMap from rustdoc_json_types here, instead of @@ -148,7 +147,7 @@ fn target(sess: &rustc_session::Session) -> types::Target { .copied() .filter(|(_, stability, _)| { // Describe only target features which the user can toggle - stability.is_toggle_permitted(sess).is_ok() + stability.toggle_allowed().is_ok() }) .map(|(name, stability, implied_features)| { types::TargetFeature { @@ -164,7 +163,7 @@ fn target(sess: &rustc_session::Session) -> types::Target { // Imply only target features which the user can toggle feature_stability .get(name) - .map(|stability| stability.is_toggle_permitted(sess).is_ok()) + .map(|stability| stability.toggle_allowed().is_ok()) .unwrap_or(false) }) .map(String::from) @@ -377,8 +376,34 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { self.serialize_and_write(output_crate, BufWriter::new(stdout().lock()), "") } } - - fn cache(&self) -> &Cache { - &self.cache - } +} + +// Some nodes are used a lot. Make sure they don't unintentionally get bigger. +// +// These assertions are here, not in `src/rustdoc-json-types/lib.rs` where the types are defined, +// because we have access to `static_assert_size` here. +#[cfg(target_pointer_width = "64")] +mod size_asserts { + use rustc_data_structures::static_assert_size; + + use super::types::*; + // tidy-alphabetical-start + static_assert_size!(AssocItemConstraint, 112); + static_assert_size!(Crate, 184); + static_assert_size!(ExternalCrate, 48); + static_assert_size!(FunctionPointer, 168); + static_assert_size!(GenericArg, 80); + static_assert_size!(GenericArgs, 104); + static_assert_size!(GenericBound, 72); + static_assert_size!(GenericParamDef, 136); + static_assert_size!(Impl, 304); + // `Item` contains a `PathBuf`, which is different sizes on different OSes. + static_assert_size!(Item, 528 + size_of::()); + static_assert_size!(ItemSummary, 32); + static_assert_size!(PolyTrait, 64); + static_assert_size!(PreciseCapturingArg, 32); + static_assert_size!(TargetFeature, 80); + static_assert_size!(Type, 80); + static_assert_size!(WherePredicate, 160); + // tidy-alphabetical-end } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index f4e4cd924f7f..2339a6b69cd8 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -35,7 +35,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> }); let local_crate = ExternalCrate { crate_num: LOCAL_CRATE }; - let prims: FxHashSet = local_crate.primitives(tcx).iter().map(|p| p.1).collect(); + let prims: FxHashSet = local_crate.primitives(tcx).map(|(_, p)| p).collect(); let crate_items = { let mut coll = ItemAndAliasCollector::new(&cx.cache); diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index 9662dd85d678..91cddbe5a5bc 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -6,8 +6,8 @@ use std::sync::Arc; use rustc_data_structures::sync::Lock; use rustc_errors::emitter::Emitter; use rustc_errors::registry::Registry; -use rustc_errors::translation::{Translate, to_fluent_args}; -use rustc_errors::{Applicability, DiagCtxt, DiagInner, LazyFallbackBundle}; +use rustc_errors::translation::{Translator, to_fluent_args}; +use rustc_errors::{Applicability, DiagCtxt, DiagInner}; use rustc_parse::{source_str_to_stream, unwrap_or_emit_fatal}; use rustc_resolve::rustdoc::source_span_for_markdown_range; use rustc_session::parse::ParseSess; @@ -36,11 +36,8 @@ fn check_rust_syntax( code_block: RustCodeBlock, ) { let buffer = Arc::new(Lock::new(Buffer::default())); - let fallback_bundle = rustc_errors::fallback_fluent_bundle( - rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), - false, - ); - let emitter = BufferEmitter { buffer: Arc::clone(&buffer), fallback_bundle }; + let translator = rustc_driver::default_translator(); + let emitter = BufferEmitter { buffer: Arc::clone(&buffer), translator }; let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings(); @@ -149,17 +146,7 @@ struct Buffer { struct BufferEmitter { buffer: Arc>, - fallback_bundle: LazyFallbackBundle, -} - -impl Translate for BufferEmitter { - fn fluent_bundle(&self) -> Option<&rustc_errors::FluentBundle> { - None - } - - fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { - &self.fallback_bundle - } + translator: Translator, } impl Emitter for BufferEmitter { @@ -168,6 +155,7 @@ impl Emitter for BufferEmitter { let fluent_args = to_fluent_args(diag.args.iter()); let translated_main_message = self + .translator .translate_message(&diag.messages[0].0, &fluent_args) .unwrap_or_else(|e| panic!("{e}")); @@ -180,4 +168,8 @@ impl Emitter for BufferEmitter { fn source_map(&self) -> Option<&SourceMap> { None } + + fn translator(&self) -> &Translator { + &self.translator + } } diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 1f93895ae076..0e72ddd9db1e 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -37,8 +37,8 @@ pub type FxHashMap = HashMap; // re-export for use in src/librustdoc // will instead cause conflicts. See #94591 for more. (This paragraph and the "Latest feature" line // are deliberately not in a doc comment, because they need not be in public docs.) // -// Latest feature: Pretty printing of inline attributes changed -pub const FORMAT_VERSION: u32 = 48; +// Latest feature: Pretty printing of no_mangle attributes changed +pub const FORMAT_VERSION: u32 = 53; /// The root of the emitted JSON blob. /// @@ -277,8 +277,8 @@ pub struct PolyTrait { /// A set of generic arguments provided to a path segment, e.g. /// /// ```text -/// std::option::Option::::None -/// ^^^^^ +/// std::option::Option +/// ^^^^^ /// ``` #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] @@ -331,7 +331,7 @@ pub enum GenericArg { Const(Constant), /// A generic argument that's explicitly set to be inferred. /// ```text - /// std::vec::Vec::<_>::new() + /// std::vec::Vec::<_> /// ^ /// ``` Infer, @@ -362,7 +362,7 @@ pub struct AssocItemConstraint { /// The name of the associated type/constant. pub name: String, /// Arguments provided to the associated type/constant. - pub args: GenericArgs, + pub args: Option>, /// The kind of bound applied to the associated type/constant. pub binding: AssocItemConstraintKind, } @@ -1118,7 +1118,7 @@ pub enum Type { /// as BetterIterator>::Item<'static> /// // ^^^^^^^^^ /// ``` - args: Box, + args: Option>, /// The type with which this type is associated. /// /// ```ignore (incomplete expression) diff --git a/src/tools/cargo b/src/tools/cargo index 2251525ae503..409fed7dc155 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 2251525ae503fa196f6d7f9ce6d32eccb2d5f044 +Subproject commit 409fed7dc1553d49cb9a8c0637d12d65571346ce diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 3a76c61489e2..13cf82a062b5 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -58,6 +58,7 @@ rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" } [features] integration = ["dep:tempfile"] internal = ["dep:clippy_lints_internal", "dep:tempfile"] +jemalloc = [] [package.metadata.rust-analyzer] # This package uses #[feature(rustc_private)] diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs index 08592f2521f7..3b827cc5603e 100644 --- a/src/tools/clippy/clippy_dev/src/update_lints.rs +++ b/src/tools/clippy/clippy_dev/src/update_lints.rs @@ -2,6 +2,7 @@ use crate::utils::{ ErrAction, File, FileUpdater, RustSearcher, Token, UpdateMode, UpdateStatus, expect_action, update_text_region_fn, }; use itertools::Itertools; +use rustc_lexer::{LiteralKind, TokenKind, tokenize}; use std::collections::HashSet; use std::fmt::Write; use std::ops::Range; @@ -342,7 +343,7 @@ fn parse_str_lit(s: &str) -> String { .and_then(|s| s.strip_suffix('"')) .unwrap_or_else(|| panic!("expected quoted string, found `{s}`")); let mut res = String::with_capacity(s.len()); - rustc_literal_escaper::unescape_unicode(s, mode, &mut |_, ch| { + rustc_literal_escaper::unescape_str(s, |range, ch| { if let Ok(ch) = ch { res.push(ch); } diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs index ae36bb76117d..8f95e44bf853 100644 --- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs @@ -56,7 +56,7 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) - .and_then(|trait_id| { cx.tcx.associated_items(trait_id).find_by_ident_and_kind( cx.tcx, - Ident::from_str("Output"), + Ident::with_dummy_span(sym::Output), ty::AssocTag::Type, trait_id, ) diff --git a/src/tools/clippy/clippy_lints/src/casts/manual_dangling_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/manual_dangling_ptr.rs index 61dfc0fc0425..d9e88d6a401c 100644 --- a/src/tools/clippy/clippy_lints/src/casts/manual_dangling_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/manual_dangling_ptr.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::SpanRangeExt; -use clippy_utils::{expr_or_init, path_def_id, paths, std_or_core}; +use clippy_utils::{expr_or_init, is_path_diagnostic_item, std_or_core, sym}; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, Ty, TyKind}; @@ -53,8 +53,7 @@ fn is_expr_const_aligned(cx: &LateContext<'_>, expr: &Expr<'_>, to: &Ty<'_>) -> fn is_align_of_call(cx: &LateContext<'_>, fun: &Expr<'_>, to: &Ty<'_>) -> bool { if let ExprKind::Path(QPath::Resolved(_, path)) = fun.kind - && let Some(fun_id) = path_def_id(cx, fun) - && paths::ALIGN_OF.matches(cx, fun_id) + && is_path_diagnostic_item(cx, fun, sym::mem_align_of) && let Some(args) = path.segments.last().and_then(|seg| seg.args) && let [GenericArg::Type(generic_ty)] = args.args { diff --git a/src/tools/clippy/clippy_lints/src/doc/doc_suspicious_footnotes.rs b/src/tools/clippy/clippy_lints/src/doc/doc_suspicious_footnotes.rs index 289b6b915d46..d3c396869766 100644 --- a/src/tools/clippy/clippy_lints/src/doc/doc_suspicious_footnotes.rs +++ b/src/tools/clippy/clippy_lints/src/doc/doc_suspicious_footnotes.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; +use rustc_ast::attr::AttributeExt as _; use rustc_ast::token::CommentKind; use rustc_errors::Applicability; use rustc_hir::{AttrStyle, Attribute}; @@ -43,13 +44,19 @@ pub fn check(cx: &LateContext<'_>, doc: &str, range: Range, fragments: &F "looks like a footnote ref, but has no matching footnote", |diag| { if this_fragment.kind == DocFragmentKind::SugaredDoc { - let (doc_attr, (_, doc_attr_comment_kind)) = attrs + let (doc_attr, (_, doc_attr_comment_kind), attr_style) = attrs .iter() .filter(|attr| attr.span().overlaps(this_fragment.span)) .rev() - .find_map(|attr| Some((attr, attr.doc_str_and_comment_kind()?))) + .find_map(|attr| { + Some(( + attr, + attr.doc_str_and_comment_kind()?, + attr.doc_resolution_scope()?, + )) + }) .unwrap(); - let (to_add, terminator) = match (doc_attr_comment_kind, doc_attr.style()) { + let (to_add, terminator) = match (doc_attr_comment_kind, attr_style) { (CommentKind::Line, AttrStyle::Outer) => ("\n///\n/// ", ""), (CommentKind::Line, AttrStyle::Inner) => ("\n//!\n//! ", ""), (CommentKind::Block, AttrStyle::Outer) => ("\n/** ", " */"), diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs index ec4538039a91..7ba11c20f456 100644 --- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs +++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs @@ -42,9 +42,8 @@ pub fn check( let mut test_attr_spans = vec![]; let filename = FileName::anon_source_code(&code); - let fallback_bundle = - rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false); - let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle); + let translator = rustc_driver::default_translator(); + let emitter = HumanEmitter::new(Box::new(io::sink()), translator); let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings(); #[expect(clippy::arc_with_non_send_sync)] // `Arc` is expected by with_dcx let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 6ed7c87915b2..b0077a9b05fe 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -7,6 +7,7 @@ use clippy_utils::{ get_path_from_caller_to_method_type, is_adjusted, is_no_std_crate, path_to_local, path_to_local_id, }; use rustc_abi::ExternAbi; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_errors::Applicability; use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind}; use rustc_infer::infer::TyCtxtInferExt; @@ -155,7 +156,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx let sig = match callee_ty_adjusted.kind() { ty::FnDef(def, _) => { // Rewriting `x(|| f())` to `x(f)` where f is marked `#[track_caller]` moves the `Location` - if cx.tcx.has_attr(*def, sym::track_caller) { + if find_attr!(cx.tcx.get_all_attrs(*def), AttributeKind::TrackCaller(..)) { return; } @@ -236,7 +237,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx }, ExprKind::MethodCall(path, self_, args, _) if check_inputs(typeck, body.params, Some(self_), args) => { if let Some(method_def_id) = typeck.type_dependent_def_id(body.value.hir_id) - && !cx.tcx.has_attr(method_def_id, sym::track_caller) + && !find_attr!(cx.tcx.get_all_attrs(method_def_id), AttributeKind::TrackCaller(..)) && check_sig(closure_sig, cx.tcx.fn_sig(method_def_id).skip_binder().skip_binder()) { let mut app = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 70655838b6af..c0c23e217fd4 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -15,6 +15,8 @@ use clippy_utils::ty::is_must_use_ty; use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{return_ty, trait_ref_of_method}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; +use rustc_span::Symbol; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use core::ops::ControlFlow; @@ -22,7 +24,7 @@ use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT}; pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { let attrs = cx.tcx.hir_attrs(item.hir_id()); - let attr = cx.tcx.get_attr(item.owner_id, sym::must_use); + let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::MustUse { span, reason } => (span, reason)); if let hir::ItemKind::Fn { ref sig, body: ref body_id, @@ -31,9 +33,9 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> { let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); - if let Some(attr) = attr { - check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig); - } else if is_public && !is_proc_macro(attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) { + if let Some((attr_span, reason)) = attr { + check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, *attr_span, *reason, attrs, sig); + } else if is_public && !is_proc_macro(attrs) && !find_attr!(attrs, AttributeKind::NoMangle(..)) { check_must_use_candidate( cx, sig.decl, @@ -52,9 +54,9 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir_attrs(item.hir_id()); - let attr = cx.tcx.get_attr(item.owner_id, sym::must_use); - if let Some(attr) = attr { - check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig); + let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::MustUse { span, reason } => (span, reason)); + if let Some((attr_span, reason)) = attr { + check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, *attr_span, *reason, attrs, sig); } else if is_public && !is_proc_macro(attrs) && trait_ref_of_method(cx, item.owner_id).is_none() { check_must_use_candidate( cx, @@ -75,9 +77,9 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir_attrs(item.hir_id()); - let attr = cx.tcx.get_attr(item.owner_id, sym::must_use); - if let Some(attr) = attr { - check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig); + let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::MustUse { span, reason } => (span, reason)); + if let Some((attr_span, reason)) = attr { + check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, *attr_span, *reason, attrs, sig); } else if let hir::TraitFn::Provided(eid) = *eid { let body = cx.tcx.hir_body(eid); if attr.is_none() && is_public && !is_proc_macro(attrs) { @@ -103,7 +105,8 @@ fn check_needless_must_use( item_id: hir::OwnerId, item_span: Span, fn_header_span: Span, - attr: &Attribute, + attr_span: Span, + reason: Option, attrs: &[Attribute], sig: &FnSig<'_>, ) { @@ -119,7 +122,7 @@ fn check_needless_must_use( "this unit-returning function has a `#[must_use]` attribute", |diag| { diag.span_suggestion( - attr.span(), + attr_span, "remove the attribute", "", Applicability::MachineApplicable, @@ -137,11 +140,11 @@ fn check_needless_must_use( MUST_USE_UNIT, fn_header_span, "this unit-returning function has a `#[must_use]` attribute", - Some(attr.span()), + Some(attr_span), "remove `must_use`", ); } - } else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) { + } else if reason.is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) { // Ignore async functions unless Future::Output type is a must_use type if sig.header.is_async() { let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); diff --git a/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs b/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs index b55c11f2d5b6..922db174e3d4 100644 --- a/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs +++ b/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; use clippy_utils::msrvs::Msrv; -use clippy_utils::{is_none_arm, msrvs, paths, peel_hir_expr_refs, sym}; +use clippy_utils::{is_none_arm, msrvs, peel_hir_expr_refs, sym}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Arm, Expr, ExprKind, LangItem, Pat, PatKind, QPath, is_range_literal}; @@ -220,5 +220,5 @@ fn is_empty_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { } fn is_slice_from_ref(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - paths::SLICE_FROM_REF.matches_path(cx, expr) + clippy_utils::is_path_diagnostic_item(cx, expr, sym::slice_from_ref) } diff --git a/src/tools/clippy/clippy_lints/src/methods/io_other_error.rs b/src/tools/clippy/clippy_lints/src/methods/io_other_error.rs index ec4b9c7ae2ee..9276261606e1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/io_other_error.rs +++ b/src/tools/clippy/clippy_lints/src/methods/io_other_error.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::{expr_or_init, paths}; +use clippy_utils::{expr_or_init, is_path_diagnostic_item, sym}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::LateContext; @@ -10,8 +10,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, path: &Expr<'_>, args && !expr.span.from_expansion() && !error_kind.span.from_expansion() && let ExprKind::Path(QPath::TypeRelative(_, new_segment)) = path.kind - && paths::IO_ERROR_NEW.matches_path(cx, path) - && paths::IO_ERRORKIND_OTHER_CTOR.matches_path(cx, expr_or_init(cx, error_kind)) + && is_path_diagnostic_item(cx, path, sym::io_error_new) + && let ExprKind::Path(QPath::Resolved(_, init_path)) = &expr_or_init(cx, error_kind).kind + && let [.., error_kind_ty, error_kind_variant] = init_path.segments + && cx.tcx.is_diagnostic_item(sym::io_errorkind, error_kind_ty.res.def_id()) + && error_kind_variant.ident.name == sym::Other && msrv.meets(cx, msrvs::IO_ERROR_OTHER) { span_lint_and_then( diff --git a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs index b71dde906918..0159c5d2ac1b 100644 --- a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs +++ b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs @@ -6,6 +6,8 @@ use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::{BytePos, Pos}; +use rustc_attr_data_structures::AttributeKind; +use rustc_hir::Attribute; declare_clippy_lint! { /// ### What it does @@ -44,8 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi { let mut app = Applicability::MaybeIncorrect; let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(ident.span.lo()), "..", &mut app); for attr in attrs { - if let Some(ident) = attr.ident() - && ident.name == rustc_span::sym::no_mangle + if let Attribute::Parsed(AttributeKind::NoMangle(attr_span)) = attr && fn_sig.header.abi == ExternAbi::Rust && let Some((fn_attrs, _)) = fn_snippet.rsplit_once("fn") && !fn_attrs.contains("extern") @@ -54,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi { .span .with_lo(fn_sig.span.lo() + BytePos::from_usize(fn_attrs.len())) .shrink_to_lo(); - let attr_snippet = snippet(cx, attr.span(), ".."); + let attr_snippet = snippet(cx, *attr_span, ".."); span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs index 07ae92fa9843..1b304dc57680 100644 --- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs +++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs @@ -6,7 +6,9 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::declare_lint_pass; -use rustc_span::{Span, sym}; +use rustc_span::{Span}; +use rustc_attr_data_structures::AttributeKind; +use rustc_attr_data_structures::find_attr; declare_clippy_lint! { /// ### What it does @@ -74,7 +76,10 @@ fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, spa // We only show this warning for public exported methods. && cx.effective_visibilities.is_exported(fn_def) // We don't want to emit this lint if the `#[must_use]` attribute is already there. - && !cx.tcx.hir_attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use)) + && !find_attr!( + cx.tcx.hir_attrs(owner_id.into()), + AttributeKind::MustUse { .. } + ) && cx.tcx.visibility(fn_def.to_def_id()).is_public() && let ret_ty = return_ty(cx, owner_id) && let self_arg = nth_arg(cx, owner_id, 0) diff --git a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs index 54d09ff9ee40..dda2f8cc1d00 100644 --- a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs +++ b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs @@ -3,7 +3,7 @@ use clippy_utils::higher::VecArgs; use clippy_utils::macros::root_macro_call_first_node; use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; -use clippy_utils::{is_no_std_crate, paths}; +use clippy_utils::{is_no_std_crate, sym}; use rustc_ast::{LitIntType, LitKind, UintTy}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem, QPath, StructTailExpr}; @@ -100,7 +100,7 @@ impl LateLintPass<'_> for SingleRangeInVecInit { && let Some(start_snippet) = start.span.get_source_text(cx) && let Some(end_snippet) = end.span.get_source_text(cx) { - let should_emit_every_value = if let Some(step_def_id) = paths::ITER_STEP.only(cx) + let should_emit_every_value = if let Some(step_def_id) = cx.tcx.get_diagnostic_item(sym::range_step) && implements_trait(cx, ty, step_def_id, &[]) { true diff --git a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs index 7d7d74f27b3c..3e847543e1c1 100644 --- a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs +++ b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs @@ -2,7 +2,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{is_in_const_context, paths, sym}; +use clippy_utils::{is_in_const_context, is_path_diagnostic_item, sym}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome { } }, hir::ExprKind::Call(to_digits_call, [char_arg, radix_arg]) => { - if paths::CHAR_TO_DIGIT.matches_path(cx, to_digits_call) { + if is_path_diagnostic_item(cx, to_digits_call, sym::char_to_digit) { Some((false, char_arg, radix_arg)) } else { None diff --git a/src/tools/clippy/clippy_lints/src/useless_concat.rs b/src/tools/clippy/clippy_lints/src/useless_concat.rs index 1ed1fbb3b9c6..96845adb04a2 100644 --- a/src/tools/clippy/clippy_lints/src/useless_concat.rs +++ b/src/tools/clippy/clippy_lints/src/useless_concat.rs @@ -1,8 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::macros::macro_backtrace; -use clippy_utils::paths::CONCAT; use clippy_utils::source::snippet_opt; -use clippy_utils::tokenize_with_text; +use clippy_utils::{sym, tokenize_with_text}; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; @@ -43,7 +42,7 @@ impl LateLintPass<'_> for UselessConcat { // Get the direct parent of the expression. && let Some(macro_call) = macro_backtrace(expr.span).next() // Check if the `concat` macro from the `core` library. - && CONCAT.matches(cx, macro_call.def_id) + && cx.tcx.is_diagnostic_item(sym::macro_concat, macro_call.def_id) // We get the original code to parse it. && let Some(original_code) = snippet_opt(cx, macro_call.span) // This check allows us to ensure that the code snippet: diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index c7a2375c8df7..913589319fcc 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1886,7 +1886,10 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { _ => None, }; - did.is_some_and(|did| cx.tcx.has_attr(did, sym::must_use)) + did.is_some_and(|did| find_attr!( + cx.tcx.get_all_attrs(did), + AttributeKind::MustUse { ..} + )) } /// Checks if a function's body represents the identity function. Looks for bodies of the form: diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index f37a609497eb..8bbcb220210a 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -126,15 +126,6 @@ path_macros! { macro_path: PathNS::Macro, } -// Paths in `core`/`alloc`/`std`. This should be avoided and cleaned up by adding diagnostic items. -pub static ALIGN_OF: PathLookup = value_path!(core::mem::align_of); -pub static CHAR_TO_DIGIT: PathLookup = value_path!(char::to_digit); -pub static CONCAT: PathLookup = macro_path!(core::concat); -pub static IO_ERROR_NEW: PathLookup = value_path!(std::io::Error::new); -pub static IO_ERRORKIND_OTHER_CTOR: PathLookup = value_path!(std::io::ErrorKind::Other); -pub static ITER_STEP: PathLookup = type_path!(core::iter::Step); -pub static SLICE_FROM_REF: PathLookup = value_path!(core::slice::from_ref); - // Paths in external crates pub static FUTURES_IO_ASYNCREADEXT: PathLookup = type_path!(futures_util::AsyncReadExt); pub static FUTURES_IO_ASYNCWRITEEXT: PathLookup = type_path!(futures_util::AsyncWriteExt); diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 32a992ccc2d7..782b079ce093 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -31,6 +31,8 @@ use rustc_trait_selection::traits::{Obligation, ObligationCause}; use std::assert_matches::debug_assert_matches; use std::collections::hash_map::Entry; use std::iter; +use rustc_attr_data_structures::find_attr; +use rustc_attr_data_structures::AttributeKind; use crate::path_res; use crate::paths::{PathNS, lookup_path_str}; @@ -326,8 +328,14 @@ pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { // Returns whether the type has #[must_use] attribute pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { - ty::Adt(adt, _) => cx.tcx.has_attr(adt.did(), sym::must_use), - ty::Foreign(did) => cx.tcx.has_attr(*did, sym::must_use), + ty::Adt(adt, _) => find_attr!( + cx.tcx.get_all_attrs(adt.did()), + AttributeKind::MustUse { ..} + ), + ty::Foreign(did) => find_attr!( + cx.tcx.get_all_attrs(*did), + AttributeKind::MustUse { ..} + ), ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => { // for the Array case we don't need to care for the len == 0 case // because we don't want to lint functions returning empty arrays @@ -337,7 +345,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { ty::Alias(ty::Opaque, AliasTy { def_id, .. }) => { for (predicate, _) in cx.tcx.explicit_item_self_bounds(def_id).skip_binder() { if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() - && cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) + && find_attr!(cx.tcx.get_all_attrs(trait_predicate.trait_ref.def_id), AttributeKind::MustUse { ..}) { return true; } @@ -347,7 +355,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { ty::Dynamic(binder, _, _) => { for predicate in *binder { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() - && cx.tcx.has_attr(trait_ref.def_id, sym::must_use) + && find_attr!(cx.tcx.get_all_attrs(trait_ref.def_id), AttributeKind::MustUse { ..}) { return true; } diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 37adb14169a3..426ba870f5f6 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -13,6 +13,11 @@ extern crate rustc_interface; extern crate rustc_session; extern crate rustc_span; +// See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs +// about jemalloc. +#[cfg(feature = "jemalloc")] +extern crate tikv_jemalloc_sys as jemalloc_sys; + use clippy_utils::sym; use rustc_interface::interface; use rustc_session::EarlyDiagCtxt; @@ -181,6 +186,36 @@ const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/ne #[allow(clippy::too_many_lines)] #[allow(clippy::ignored_unit_patterns)] pub fn main() { + // See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs + // about jemalloc. + #[cfg(feature = "jemalloc")] + { + use std::os::raw::{c_int, c_void}; + + #[used] + static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc; + #[used] + static _F2: unsafe extern "C" fn(*mut *mut c_void, usize, usize) -> c_int = jemalloc_sys::posix_memalign; + #[used] + static _F3: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::aligned_alloc; + #[used] + static _F4: unsafe extern "C" fn(usize) -> *mut c_void = jemalloc_sys::malloc; + #[used] + static _F5: unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void = jemalloc_sys::realloc; + #[used] + static _F6: unsafe extern "C" fn(*mut c_void) = jemalloc_sys::free; + + #[cfg(target_os = "macos")] + { + unsafe extern "C" { + fn _rjem_je_zone_register(); + } + + #[used] + static _F7: unsafe extern "C" fn() = _rjem_je_zone_register; + } + } + let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); rustc_driver::init_rustc_env_logger(&early_dcx); diff --git a/src/tools/clippy/tests/ui/author/macro_in_closure.stdout b/src/tools/clippy/tests/ui/author/macro_in_closure.stdout index 5f8a4ce23630..49595e2fec25 100644 --- a/src/tools/clippy/tests/ui/author/macro_in_closure.stdout +++ b/src/tools/clippy/tests/ui/author/macro_in_closure.stdout @@ -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 } diff --git a/src/tools/clippy/tests/ui/author/macro_in_loop.stdout b/src/tools/clippy/tests/ui/author/macro_in_loop.stdout index ecc252543117..4fc7b49464db 100644 --- a/src/tools/clippy/tests/ui/author/macro_in_loop.stdout +++ b/src/tools/clippy/tests/ui/author/macro_in_loop.stdout @@ -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() { diff --git a/src/tools/clippy/tests/ui/manual_inspect.fixed b/src/tools/clippy/tests/ui/manual_inspect.fixed index 9b768dbad700..00a19155a516 100644 --- a/src/tools/clippy/tests/ui/manual_inspect.fixed +++ b/src/tools/clippy/tests/ui/manual_inspect.fixed @@ -154,7 +154,6 @@ fn main() { }); let _ = [0] - //~^ suspicious_map .into_iter() .inspect(|&x| { //~^ manual_inspect diff --git a/src/tools/clippy/tests/ui/manual_inspect.rs b/src/tools/clippy/tests/ui/manual_inspect.rs index e679636201e6..b3b17139cde3 100644 --- a/src/tools/clippy/tests/ui/manual_inspect.rs +++ b/src/tools/clippy/tests/ui/manual_inspect.rs @@ -165,7 +165,6 @@ fn main() { }); let _ = [0] - //~^ suspicious_map .into_iter() .map(|x| { //~^ manual_inspect diff --git a/src/tools/clippy/tests/ui/manual_inspect.stderr b/src/tools/clippy/tests/ui/manual_inspect.stderr index 78b085fdfca3..70c00c1f7558 100644 --- a/src/tools/clippy/tests/ui/manual_inspect.stderr +++ b/src/tools/clippy/tests/ui/manual_inspect.stderr @@ -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 diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index b5a2b7feac9d..9fa26305f6b0 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -16,6 +16,8 @@ pub enum ErrorKind { Suggestion, Warning, Raw, + /// Used for better recovery and diagnostics in compiletest. + Unknown, } impl ErrorKind { @@ -31,21 +33,25 @@ impl ErrorKind { /// Either the canonical uppercase string, or some additional versions for compatibility. /// FIXME: consider keeping only the canonical versions here. - pub fn from_user_str(s: &str) -> ErrorKind { - match s { + fn from_user_str(s: &str) -> Option { + Some(match s { "HELP" | "help" => ErrorKind::Help, "ERROR" | "error" => ErrorKind::Error, - // `MONO_ITEM` makes annotations in `codegen-units` tests syntactically correct, - // but those tests never use the error kind later on. - "NOTE" | "note" | "MONO_ITEM" => ErrorKind::Note, + "NOTE" | "note" => ErrorKind::Note, "SUGGESTION" => ErrorKind::Suggestion, "WARN" | "WARNING" | "warn" | "warning" => ErrorKind::Warning, "RAW" => ErrorKind::Raw, - _ => panic!( + _ => return None, + }) + } + + pub fn expect_from_user_str(s: &str) -> ErrorKind { + ErrorKind::from_user_str(s).unwrap_or_else(|| { + panic!( "unexpected diagnostic kind `{s}`, expected \ - `ERROR`, `WARN`, `NOTE`, `HELP` or `SUGGESTION`" - ), - } + `ERROR`, `WARN`, `NOTE`, `HELP`, `SUGGESTION` or `RAW`" + ) + }) } } @@ -58,6 +64,7 @@ impl fmt::Display for ErrorKind { ErrorKind::Suggestion => write!(f, "SUGGESTION"), ErrorKind::Warning => write!(f, "WARN"), ErrorKind::Raw => write!(f, "RAW"), + ErrorKind::Unknown => write!(f, "UNKNOWN"), } } } @@ -65,6 +72,7 @@ impl fmt::Display for ErrorKind { #[derive(Debug)] pub struct Error { pub line_num: Option, + pub column_num: Option, /// What kind of message we expect (e.g., warning, error, suggestion). pub kind: ErrorKind, pub msg: String, @@ -74,17 +82,6 @@ pub struct Error { pub require_annotation: bool, } -impl Error { - pub fn render_for_expected(&self) -> String { - use colored::Colorize; - format!("{: <10}line {: >3}: {}", self.kind, self.line_num_str(), self.msg.cyan()) - } - - pub fn line_num_str(&self) -> String { - self.line_num.map_or("?".to_string(), |line_num| line_num.to_string()) - } -} - /// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE" /// The former is a "follow" that inherits its target from the preceding line; /// the latter is an "adjusts" that goes that many lines up. @@ -168,8 +165,10 @@ fn parse_expected( let rest = line[tag.end()..].trim_start(); let (kind_str, _) = rest.split_once(|c: char| c != '_' && !c.is_ascii_alphabetic()).unwrap_or((rest, "")); - let kind = ErrorKind::from_user_str(kind_str); - let untrimmed_msg = &rest[kind_str.len()..]; + let (kind, untrimmed_msg) = match ErrorKind::from_user_str(kind_str) { + Some(kind) => (kind, &rest[kind_str.len()..]), + None => (ErrorKind::Unknown, rest), + }; let msg = untrimmed_msg.strip_prefix(':').unwrap_or(untrimmed_msg).trim().to_owned(); let line_num_adjust = &captures["adjust"]; @@ -182,6 +181,7 @@ fn parse_expected( } else { (false, Some(line_num - line_num_adjust.len())) }; + let column_num = Some(tag.start() + 1); debug!( "line={:?} tag={:?} follow_prev={:?} kind={:?} msg={:?}", @@ -191,7 +191,7 @@ fn parse_expected( kind, msg ); - Some((follow_prev, Error { line_num, kind, msg, require_annotation: true })) + Some((follow_prev, Error { line_num, column_num, kind, msg, require_annotation: true })) } #[cfg(test)] diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 8bee9caacc94..2b203bb309c6 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -593,7 +593,7 @@ impl TestProps { config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS) { self.dont_require_annotations - .insert(ErrorKind::from_user_str(err_kind.trim())); + .insert(ErrorKind::expect_from_user_str(err_kind.trim())); } }, ); diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 6ed2b52c66d2..a8e6416e56c8 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -36,9 +36,7 @@ struct UnusedExternNotification { struct DiagnosticSpan { file_name: String, line_start: usize, - line_end: usize, column_start: usize, - column_end: usize, is_primary: bool, label: Option, suggested_replacement: Option, @@ -148,6 +146,7 @@ pub fn parse_output(file_name: &str, output: &str) -> Vec { Ok(diagnostic) => push_actual_errors(&mut errors, &diagnostic, &[], file_name), Err(_) => errors.push(Error { line_num: None, + column_num: None, kind: ErrorKind::Raw, msg: line.to_string(), require_annotation: false, @@ -193,25 +192,9 @@ fn push_actual_errors( // also ensure that `//~ ERROR E123` *always* works. The // assumption is that these multi-line error messages are on their // way out anyhow. - let with_code = |span: Option<&DiagnosticSpan>, text: &str| { - // FIXME(#33000) -- it'd be better to use a dedicated - // UI harness than to include the line/col number like - // this, but some current tests rely on it. - // - // Note: Do NOT include the filename. These can easily - // cause false matches where the expected message - // appears in the filename, and hence the message - // changes but the test still passes. - let span_str = match span { - Some(DiagnosticSpan { line_start, column_start, line_end, column_end, .. }) => { - format!("{line_start}:{column_start}: {line_end}:{column_end}") - } - None => format!("?:?: ?:?"), - }; - match &diagnostic.code { - Some(code) => format!("{span_str}: {text} [{}]", code.code), - None => format!("{span_str}: {text}"), - } + let with_code = |text| match &diagnostic.code { + Some(code) => format!("{text} [{}]", code.code), + None => format!("{text}"), }; // Convert multi-line messages into multiple errors. @@ -225,8 +208,9 @@ fn push_actual_errors( || Regex::new(r"aborting due to \d+ previous errors?|\d+ warnings? emitted").unwrap(); errors.push(Error { line_num: None, + column_num: None, kind, - msg: with_code(None, first_line), + msg: with_code(first_line), require_annotation: diagnostic.level != "failure-note" && !RE.get_or_init(re_init).is_match(first_line), }); @@ -234,8 +218,9 @@ fn push_actual_errors( for span in primary_spans { errors.push(Error { line_num: Some(span.line_start), + column_num: Some(span.column_start), kind, - msg: with_code(Some(span), first_line), + msg: with_code(first_line), require_annotation: true, }); } @@ -244,16 +229,18 @@ fn push_actual_errors( if primary_spans.is_empty() { errors.push(Error { line_num: None, + column_num: None, kind, - msg: with_code(None, next_line), + msg: with_code(next_line), require_annotation: false, }); } else { for span in primary_spans { errors.push(Error { line_num: Some(span.line_start), + column_num: Some(span.column_start), kind, - msg: with_code(Some(span), next_line), + msg: with_code(next_line), require_annotation: false, }); } @@ -266,6 +253,7 @@ fn push_actual_errors( for (index, line) in suggested_replacement.lines().enumerate() { errors.push(Error { line_num: Some(span.line_start + index), + column_num: Some(span.column_start), kind: ErrorKind::Suggestion, msg: line.to_string(), // Empty suggestions (suggestions to remove something) are common @@ -288,6 +276,7 @@ fn push_actual_errors( if let Some(label) = &span.label { errors.push(Error { line_num: Some(span.line_start), + column_num: Some(span.column_start), kind: ErrorKind::Note, msg: label.clone(), // Empty labels (only underlining spans) are common and do not need annotations. @@ -310,6 +299,7 @@ fn push_backtrace( if Path::new(&expansion.span.file_name) == Path::new(&file_name) { errors.push(Error { line_num: Some(expansion.span.line_start), + column_num: Some(expansion.span.column_start), kind: ErrorKind::Note, msg: format!("in this expansion of {}", expansion.macro_decl_name), require_annotation: true, diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 42c851ea9991..980e89889abb 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -11,7 +11,7 @@ use std::{env, iter, str}; use build_helper::fs::remove_and_create_dir_all; use camino::{Utf8Path, Utf8PathBuf}; -use colored::Colorize; +use colored::{Color, Colorize}; use regex::{Captures, Regex}; use tracing::*; @@ -677,9 +677,6 @@ impl<'test> TestCx<'test> { return; } - // On Windows, translate all '\' path separators to '/' - let file_name = self.testpaths.file.to_string().replace(r"\", "/"); - // On Windows, keep all '\' path separators to match the paths reported in the JSON output // from the compiler let diagnostic_file_name = if self.props.remap_src_base { @@ -704,6 +701,7 @@ impl<'test> TestCx<'test> { .map(|e| Error { msg: self.normalize_output(&e.msg, &[]), ..e }); let mut unexpected = Vec::new(); + let mut unimportant = Vec::new(); let mut found = vec![false; expected_errors.len()]; for actual_error in actual_errors { for pattern in &self.props.error_patterns { @@ -738,14 +736,9 @@ impl<'test> TestCx<'test> { && expected_kinds.contains(&actual_error.kind) && !self.props.dont_require_annotations.contains(&actual_error.kind) { - self.error(&format!( - "{}:{}: unexpected {}: '{}'", - file_name, - actual_error.line_num_str(), - actual_error.kind, - actual_error.msg - )); unexpected.push(actual_error); + } else { + unimportant.push(actual_error); } } } @@ -755,39 +748,140 @@ impl<'test> TestCx<'test> { // anything not yet found is a problem for (index, expected_error) in expected_errors.iter().enumerate() { if !found[index] { - self.error(&format!( - "{}:{}: expected {} not found: {}", - file_name, - expected_error.line_num_str(), - expected_error.kind, - expected_error.msg - )); not_found.push(expected_error); } } if !unexpected.is_empty() || !not_found.is_empty() { self.error(&format!( - "{} unexpected errors found, {} expected errors not found", + "{} unexpected diagnostics reported, {} expected diagnostics not reported", unexpected.len(), not_found.len() )); - println!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline); + + // Emit locations in a format that is short (relative paths) but "clickable" in editors. + // Also normalize path separators to `/`. + let file_name = self + .testpaths + .file + .strip_prefix(self.config.src_root.as_str()) + .unwrap_or(&self.testpaths.file) + .to_string() + .replace(r"\", "/"); + let line_str = |e: &Error| { + let line_num = e.line_num.map_or("?".to_string(), |line_num| line_num.to_string()); + // `file:?:NUM` may be confusing to editors and unclickable. + let opt_col_num = match e.column_num { + Some(col_num) if line_num != "?" => format!(":{col_num}"), + _ => "".to_string(), + }; + format!("{file_name}:{line_num}{opt_col_num}") + }; + let print_error = |e| println!("{}: {}: {}", line_str(e), e.kind, e.msg.cyan()); + let push_suggestion = + |suggestions: &mut Vec<_>, e: &Error, kind, line, msg, color, rank| { + let mut ret = String::new(); + if kind { + ret += &format!("{} {}", "with kind".color(color), e.kind); + } + if line { + if !ret.is_empty() { + ret.push(' '); + } + ret += &format!("{} {}", "on line".color(color), line_str(e)); + } + if msg { + if !ret.is_empty() { + ret.push(' '); + } + ret += &format!("{} {}", "with message".color(color), e.msg.cyan()); + } + suggestions.push((ret, rank)); + }; + let show_suggestions = |mut suggestions: Vec<_>, prefix: &str, color| { + // Only show suggestions with the highest rank. + suggestions.sort_by_key(|(_, rank)| *rank); + if let Some(&(_, top_rank)) = suggestions.first() { + for (suggestion, rank) in suggestions { + if rank == top_rank { + println!(" {} {suggestion}", prefix.color(color)); + } + } + } + }; + + // Fuzzy matching quality: + // - message and line / message and kind - great, suggested + // - only message - good, suggested + // - known line and kind - ok, suggested + // - only known line - meh, but suggested + // - others are not worth suggesting if !unexpected.is_empty() { - println!("{}", "--- unexpected errors (from JSON output) ---".green()); + let header = "--- reported in JSON output but not expected in test file ---"; + println!("{}", header.green()); for error in &unexpected { - println!("{}", error.render_for_expected()); + print_error(error); + let mut suggestions = Vec::new(); + for candidate in ¬_found { + let mut push_red_suggestion = |line, msg, rank| { + push_suggestion( + &mut suggestions, + candidate, + candidate.kind != error.kind, + line, + msg, + Color::Red, + rank, + ) + }; + if error.msg.contains(&candidate.msg) { + push_red_suggestion(candidate.line_num != error.line_num, false, 0); + } else if candidate.line_num.is_some() + && candidate.line_num == error.line_num + { + push_red_suggestion(false, true, 1); + } + } + + show_suggestions(suggestions, "expected", Color::Red); } println!("{}", "---".green()); } if !not_found.is_empty() { - println!("{}", "--- not found errors (from test file) ---".red()); + let header = "--- expected in test file but not reported in JSON output ---"; + println!("{}", header.red()); for error in ¬_found { - println!("{}", error.render_for_expected()); + print_error(error); + let mut suggestions = Vec::new(); + for candidate in unexpected.iter().chain(&unimportant) { + let mut push_green_suggestion = |line, msg, rank| { + push_suggestion( + &mut suggestions, + candidate, + candidate.kind != error.kind, + line, + msg, + Color::Green, + rank, + ) + }; + if candidate.msg.contains(&error.msg) { + push_green_suggestion(candidate.line_num != error.line_num, false, 0); + } else if candidate.line_num.is_some() + && candidate.line_num == error.line_num + { + push_green_suggestion(false, true, 1); + } + } + + show_suggestions(suggestions, "reported", Color::Green); } - println!("{}", "---\n".red()); + println!("{}", "---".red()); } - panic!("errors differ from expected"); + panic!( + "errors differ from expected\nstatus: {}\ncommand: {}\n", + proc_res.status, proc_res.cmdline + ); } } @@ -2073,7 +2167,6 @@ impl<'test> TestCx<'test> { println!("{}", String::from_utf8_lossy(&output.stdout)); eprintln!("{}", String::from_utf8_lossy(&output.stderr)); } else { - use colored::Colorize; eprintln!("warning: no pager configured, falling back to unified diff"); eprintln!( "help: try configuring a git pager (e.g. `delta`) with `git config --global core.pager delta`" diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index 029da1c18983..60e8e16e25ef 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs @@ -221,6 +221,10 @@ impl TestCx<'_> { cmd.env("REMOTE_TEST_CLIENT", remote_test_client); } + if let Some(runner) = &self.config.runner { + cmd.env("RUNNER", runner); + } + // We don't want RUSTFLAGS set from the outside to interfere with // compiler flags set in the test cases: cmd.env_remove("RUSTFLAGS"); diff --git a/src/tools/enzyme b/src/tools/enzyme index a35f4f773118..b5098d515d5e 160000 --- a/src/tools/enzyme +++ b/src/tools/enzyme @@ -1 +1 @@ -Subproject commit a35f4f773118ccfbd8d05102eb12a34097b1ee55 +Subproject commit b5098d515d5e1bd0f5470553bc0d18da9794ca8b diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index 8c9e4c8bb3a6..0a4051fcbe8c 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -271,7 +271,7 @@ impl<'a> Validator<'a> { Type::RawPointer { is_mutable: _, type_ } => self.check_type(&**type_), Type::BorrowedRef { lifetime: _, is_mutable: _, type_ } => self.check_type(&**type_), Type::QualifiedPath { name: _, args, self_type, trait_ } => { - self.check_generic_args(&**args); + self.check_opt_generic_args(&args); self.check_type(&**self_type); if let Some(trait_) = trait_ { self.check_path(trait_, PathKind::Trait); @@ -309,13 +309,12 @@ impl<'a> Validator<'a> { self.fail(&x.id, ErrorKind::Custom(format!("No entry in '$.paths' for {x:?}"))); } - if let Some(args) = &x.args { - self.check_generic_args(&**args); - } + self.check_opt_generic_args(&x.args); } - fn check_generic_args(&mut self, x: &'a GenericArgs) { - match x { + fn check_opt_generic_args(&mut self, x: &'a Option>) { + let Some(x) = x else { return }; + match &**x { GenericArgs::AngleBracketed { args, constraints } => { args.iter().for_each(|arg| self.check_generic_arg(arg)); constraints.iter().for_each(|bind| self.check_assoc_item_constraint(bind)); @@ -355,7 +354,7 @@ impl<'a> Validator<'a> { } fn check_assoc_item_constraint(&mut self, bind: &'a AssocItemConstraint) { - self.check_generic_args(&bind.args); + self.check_opt_generic_args(&bind.args); match &bind.binding { AssocItemConstraintKind::Equality(term) => self.check_term(term), AssocItemConstraintKind::Constraint(bounds) => { diff --git a/src/tools/linkchecker/linkcheck.sh b/src/tools/linkchecker/linkcheck.sh index 6c1e668a7f0d..d230610a6e79 100755 --- a/src/tools/linkchecker/linkcheck.sh +++ b/src/tools/linkchecker/linkcheck.sh @@ -98,6 +98,7 @@ then nightly_hash=$(rustc +nightly -Vv | grep commit-hash | cut -f2 -d" ") url="https://raw.githubusercontent.com/rust-lang/rust" mkdir linkchecker + curl -o linkchecker/Cargo.lock ${url}/${nightly_hash}/Cargo.lock curl -o linkchecker/Cargo.toml ${url}/${nightly_hash}/src/tools/linkchecker/Cargo.toml curl -o linkchecker/main.rs ${url}/${nightly_hash}/src/tools/linkchecker/main.rs fi diff --git a/src/tools/lint-docs/Cargo.toml b/src/tools/lint-docs/Cargo.toml index f1ffda75ac0f..e914a2df2bad 100644 --- a/src/tools/lint-docs/Cargo.toml +++ b/src/tools/lint-docs/Cargo.toml @@ -7,7 +7,7 @@ description = "A script to extract the lint documentation for the rustc book." # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rustc-literal-escaper = "0.0.2" +rustc-literal-escaper = "0.0.4" serde_json = "1.0.57" tempfile = "3.1.0" walkdir = "2.3.1" diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs index 6bb18c2bced7..b33344ca5dda 100644 --- a/src/tools/lint-docs/src/lib.rs +++ b/src/tools/lint-docs/src/lib.rs @@ -4,7 +4,7 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; -use rustc_literal_escaper::{Mode, unescape_unicode}; +use rustc_literal_escaper::unescape_str; use walkdir::WalkDir; mod groups; @@ -218,7 +218,7 @@ impl<'a> LintExtractor<'a> { } else if let Some(text) = line.strip_prefix("#[doc = \"") { let escaped = text.strip_suffix("\"]").unwrap(); let mut buf = String::new(); - unescape_unicode(escaped, Mode::Str, &mut |_, c| match c { + unescape_str(escaped, |_, res| match res { Ok(c) => buf.push(c), Err(err) => { assert!(!err.is_fatal(), "failed to unescape string literal") diff --git a/src/tools/miri/tests/pass/fn_align.rs b/src/tools/miri/tests/pass/fn_align.rs index 550bb1cb4d71..28f929958800 100644 --- a/src/tools/miri/tests/pass/fn_align.rs +++ b/src/tools/miri/tests/pass/fn_align.rs @@ -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)); } diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index a7081d4f86a2..72a1e062a38d 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -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, } -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>(&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 } diff --git a/src/tools/run-make-support/src/external_deps/rustdoc.rs b/src/tools/run-make-support/src/external_deps/rustdoc.rs index 7040fb667cfc..33e5f04d3034 100644 --- a/src/tools/run-make-support/src/external_deps/rustdoc.rs +++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs @@ -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, } -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>(&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 } diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index f37b38ac0b15..67d8c351a59f 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -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. /// @@ -83,7 +83,7 @@ pub use run::{cmd, run, run_fail, run_with_args}; /// Helpers for checking target information. pub use targets::{ - apple_os, is_aix, is_darwin, is_msvc, is_windows, is_windows_gnu, is_win7, llvm_components_contain, + apple_os, is_aix, is_darwin, is_msvc, is_windows, is_windows_gnu, is_windows_msvc, is_win7, llvm_components_contain, target, uname, }; diff --git a/src/tools/run-make-support/src/macros.rs b/src/tools/run-make-support/src/macros.rs index 9d5cc4e5876d..b9208382a982 100644 --- a/src/tools/run-make-support/src/macros.rs +++ b/src/tools/run-make-support/src/macros.rs @@ -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() } diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs index 60e711d34027..b95f3a5cfe5a 100644 --- a/src/tools/run-make-support/src/run.rs +++ b/src/tools/run-make-support/src/run.rs @@ -1,4 +1,4 @@ -use std::ffi::OsStr; +use std::ffi::{OsStr, OsString}; use std::path::PathBuf; use std::{env, panic}; @@ -21,6 +21,20 @@ fn run_common(name: &str, args: Option<&[&str]>) -> Command { // will have to be changed (and the support files will have to be uploaded). cmd.arg("0"); cmd.arg(bin_path); + cmd + } else if let Ok(runner) = std::env::var("RUNNER") { + let mut args = split_maybe_args(&runner); + + let prog = args.remove(0); + let mut cmd = Command::new(prog); + + for arg in args { + cmd.arg(arg); + } + + cmd.arg("--"); + cmd.arg(bin_path); + cmd } else { Command::new(bin_path) @@ -92,3 +106,12 @@ pub fn cmd>(program: S) -> Command { command.env("LC_ALL", "C"); // force english locale command } + +fn split_maybe_args(s: &str) -> Vec { + // FIXME(132599): implement proper env var/shell argument splitting. + s.split(' ') + .filter_map(|s| { + if s.chars().all(|c| c.is_whitespace()) { None } else { Some(OsString::from(s)) } + }) + .collect() +} diff --git a/src/tools/run-make-support/src/targets.rs b/src/tools/run-make-support/src/targets.rs index 86edbdf750bb..1ab2e2ab2be4 100644 --- a/src/tools/run-make-support/src/targets.rs +++ b/src/tools/run-make-support/src/targets.rs @@ -28,6 +28,12 @@ pub fn is_windows_gnu() -> bool { target().ends_with("windows-gnu") } +/// Check if target is windows-msvc. +#[must_use] +pub fn is_windows_msvc() -> bool { + target().ends_with("windows-msvc") +} + /// Check if target is win7. #[must_use] pub fn is_win7() -> bool { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index c618e4bdce7d..00408e95ae6f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -11,12 +11,12 @@ use syntax::{AstPtr, ast}; use triomphe::Arc; use crate::{ - AssocItemId, AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, EnumVariantId, - EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, - FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroExpander, - MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, - StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, - TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId, + AssocItemId, AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, + EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, + FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc, + MacroExpander, MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId, + ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, + TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId, attr::{Attrs, AttrsWithOwner}, expr_store::{ Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, scope::ExprScopes, @@ -90,7 +90,10 @@ pub trait InternDatabase: RootQueryDb { #[salsa::interned] fn intern_macro_rules(&self, loc: MacroRulesLoc) -> MacroRulesId; - // // endregion: items + // endregion: items + + #[salsa::interned] + fn intern_block(&self, loc: BlockLoc) -> BlockId; } #[query_group::query_group] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 03683ec9203c..efa1374a4465 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -11,7 +11,7 @@ use base_db::FxIndexSet; use cfg::CfgOptions; use either::Either; use hir_expand::{ - HirFileId, InFile, Intern, MacroDefId, + HirFileId, InFile, MacroDefId, mod_path::tool_path, name::{AsName, Name}, span_map::SpanMapRef, @@ -2148,7 +2148,7 @@ impl ExprCollector<'_> { ) -> ExprId { let block_id = self.expander.ast_id_map().ast_id_for_block(&block).map(|file_local_id| { let ast_id = self.expander.in_file(file_local_id); - BlockLoc { ast_id, module: self.module }.intern(self.db) + self.db.intern_block(BlockLoc { ast_id, module: self.module }) }); let (module, def_map) = @@ -2815,6 +2815,51 @@ impl ExprCollector<'_> { mutability: Mutability::Shared, }) }; + + // Assume that rustc version >= 1.89.0 iff lang item `format_arguments` exists + // but `format_unsafe_arg` does not + let fmt_args = + || crate::lang_item::lang_item(self.db, self.module.krate(), LangItem::FormatArguments); + let fmt_unsafe_arg = + || crate::lang_item::lang_item(self.db, self.module.krate(), LangItem::FormatUnsafeArg); + let use_format_args_since_1_89_0 = fmt_args().is_some() && fmt_unsafe_arg().is_none(); + + let idx = if use_format_args_since_1_89_0 { + self.collect_format_args_impl( + syntax_ptr, + fmt, + hygiene, + argmap, + lit_pieces, + format_options, + ) + } else { + self.collect_format_args_before_1_89_0_impl( + syntax_ptr, + fmt, + argmap, + lit_pieces, + format_options, + ) + }; + + self.source_map + .template_map + .get_or_insert_with(Default::default) + .format_args_to_captures + .insert(idx, (hygiene, mappings)); + idx + } + + /// `format_args!` expansion implementation for rustc versions < `1.89.0` + fn collect_format_args_before_1_89_0_impl( + &mut self, + syntax_ptr: AstPtr, + fmt: FormatArgs, + argmap: FxIndexSet<(usize, ArgumentType)>, + lit_pieces: ExprId, + format_options: ExprId, + ) -> ExprId { let arguments = &*fmt.arguments.arguments; let args = if arguments.is_empty() { @@ -2902,19 +2947,181 @@ impl ExprCollector<'_> { }); } - let idx = self.alloc_expr( + self.alloc_expr( Expr::Call { callee: new_v1_formatted, args: Box::new([lit_pieces, args, format_options, unsafe_arg_new]), }, syntax_ptr, - ); - self.source_map - .template_map - .get_or_insert_with(Default::default) - .format_args_to_captures - .insert(idx, (hygiene, mappings)); - idx + ) + } + + /// `format_args!` expansion implementation for rustc versions >= `1.89.0`, + /// especially since [this PR](https://github.com/rust-lang/rust/pull/140748) + fn collect_format_args_impl( + &mut self, + syntax_ptr: AstPtr, + fmt: FormatArgs, + hygiene: HygieneId, + argmap: FxIndexSet<(usize, ArgumentType)>, + lit_pieces: ExprId, + format_options: ExprId, + ) -> ExprId { + let arguments = &*fmt.arguments.arguments; + + let (let_stmts, args) = if arguments.is_empty() { + ( + // Generate: + // [] + vec![], + self.alloc_expr_desugared(Expr::Array(Array::ElementList { + elements: Box::default(), + })), + ) + } else if argmap.len() == 1 && arguments.len() == 1 { + // Only one argument, so we don't need to make the `args` tuple. + // + // Generate: + // super let args = [::new_display(&arg)]; + let args = argmap + .iter() + .map(|&(arg_index, ty)| { + let ref_arg = self.alloc_expr_desugared(Expr::Ref { + expr: arguments[arg_index].expr, + rawness: Rawness::Ref, + mutability: Mutability::Shared, + }); + self.make_argument(ref_arg, ty) + }) + .collect(); + let args = + self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: args })); + let args_name = Name::new_symbol_root(sym::args); + let args_binding = + self.alloc_binding(args_name.clone(), BindingAnnotation::Unannotated, hygiene); + let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None }); + self.add_definition_to_binding(args_binding, args_pat); + // TODO: We don't have `super let` yet. + let let_stmt = Statement::Let { + pat: args_pat, + type_ref: None, + initializer: Some(args), + else_branch: None, + }; + (vec![let_stmt], self.alloc_expr_desugared(Expr::Path(Path::from(args_name)))) + } else { + // Generate: + // super let args = (&arg0, &arg1, &...); + let args_name = Name::new_symbol_root(sym::args); + let args_binding = + self.alloc_binding(args_name.clone(), BindingAnnotation::Unannotated, hygiene); + let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None }); + self.add_definition_to_binding(args_binding, args_pat); + let elements = arguments + .iter() + .map(|arg| { + self.alloc_expr_desugared(Expr::Ref { + expr: arg.expr, + rawness: Rawness::Ref, + mutability: Mutability::Shared, + }) + }) + .collect(); + let args_tuple = self.alloc_expr_desugared(Expr::Tuple { exprs: elements }); + // TODO: We don't have `super let` yet + let let_stmt1 = Statement::Let { + pat: args_pat, + type_ref: None, + initializer: Some(args_tuple), + else_branch: None, + }; + + // Generate: + // super let args = [ + // ::new_display(args.0), + // ::new_lower_hex(args.1), + // ::new_debug(args.0), + // … + // ]; + let args = argmap + .iter() + .map(|&(arg_index, ty)| { + let args_ident_expr = + self.alloc_expr_desugared(Expr::Path(args_name.clone().into())); + let arg = self.alloc_expr_desugared(Expr::Field { + expr: args_ident_expr, + name: Name::new_tuple_field(arg_index), + }); + self.make_argument(arg, ty) + }) + .collect(); + let array = + self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: args })); + let args_binding = + self.alloc_binding(args_name.clone(), BindingAnnotation::Unannotated, hygiene); + let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None }); + self.add_definition_to_binding(args_binding, args_pat); + let let_stmt2 = Statement::Let { + pat: args_pat, + type_ref: None, + initializer: Some(array), + else_branch: None, + }; + (vec![let_stmt1, let_stmt2], self.alloc_expr_desugared(Expr::Path(args_name.into()))) + }; + + // Generate: + // &args + let args = self.alloc_expr_desugared(Expr::Ref { + expr: args, + rawness: Rawness::Ref, + mutability: Mutability::Shared, + }); + + let call_block = { + // Generate: + // unsafe { + // ::new_v1_formatted( + // lit_pieces, + // args, + // format_options, + // ) + // } + + let new_v1_formatted = LangItem::FormatArguments.ty_rel_path( + self.db, + self.module.krate(), + Name::new_symbol_root(sym::new_v1_formatted), + ); + let new_v1_formatted = + self.alloc_expr_desugared(new_v1_formatted.map_or(Expr::Missing, Expr::Path)); + let args = [lit_pieces, args, format_options]; + let call = self + .alloc_expr_desugared(Expr::Call { callee: new_v1_formatted, args: args.into() }); + + Expr::Unsafe { id: None, statements: Box::default(), tail: Some(call) } + }; + + if !let_stmts.is_empty() { + // Generate: + // { + // super let … + // super let … + // ::new_…(…) + // } + let call = self.alloc_expr_desugared(call_block); + self.alloc_expr( + Expr::Block { + id: None, + statements: let_stmts.into(), + tail: Some(call), + label: None, + }, + syntax_ptr, + ) + } else { + self.alloc_expr(call_block, syntax_ptr) + } } /// Generate a hir expression for a format_args placeholder specification. diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs index 29e249b07a72..927e280d7394 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs @@ -178,14 +178,14 @@ fn main() { } #[test] -fn desugar_builtin_format_args() { +fn desugar_builtin_format_args_before_1_89_0() { let (db, body, def) = lower( r#" -//- minicore: fmt +//- minicore: fmt_before_1_89_0 fn main() { let are = "are"; let count = 10; - builtin#format_args("\u{1b}hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!"); + builtin#format_args("\u{1b}hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", orphan = (), last = "!"); } "#, ); @@ -249,14 +249,100 @@ fn main() { builtin#lang(Count::Implied), ), ], - unsafe { - builtin#lang(UnsafeArg::new)() + { + (); + unsafe { + builtin#lang(UnsafeArg::new)() + } }, ); }"#]] .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT)) } +#[test] +fn desugar_builtin_format_args() { + let (db, body, def) = lower( + r#" +//- minicore: fmt +fn main() { + let are = "are"; + let count = 10; + builtin#format_args("\u{1b}hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", orphan = (), last = "!"); +} +"#, + ); + + expect![[r#" + fn main() { + let are = "are"; + let count = 10; + { + let args = (&"fancy", &(), &"!", &count, &are, ); + let args = [ + builtin#lang(Argument::new_display)( + args.3, + ), builtin#lang(Argument::new_display)( + args.0, + ), builtin#lang(Argument::new_debug)( + args.4, + ), builtin#lang(Argument::new_display)( + args.2, + ), + ]; + unsafe { + builtin#lang(Arguments::new_v1_formatted)( + &[ + "\u{1b}hello ", " ", " friends, we ", " ", "", + ], + &args, + &[ + builtin#lang(Placeholder::new)( + 0usize, + ' ', + builtin#lang(Alignment::Unknown), + 8u32, + builtin#lang(Count::Implied), + builtin#lang(Count::Is)( + 2, + ), + ), builtin#lang(Placeholder::new)( + 1usize, + ' ', + builtin#lang(Alignment::Unknown), + 0u32, + builtin#lang(Count::Implied), + builtin#lang(Count::Implied), + ), builtin#lang(Placeholder::new)( + 2usize, + ' ', + builtin#lang(Alignment::Unknown), + 0u32, + builtin#lang(Count::Implied), + builtin#lang(Count::Implied), + ), builtin#lang(Placeholder::new)( + 1usize, + ' ', + builtin#lang(Alignment::Unknown), + 0u32, + builtin#lang(Count::Implied), + builtin#lang(Count::Implied), + ), builtin#lang(Placeholder::new)( + 3usize, + ' ', + builtin#lang(Alignment::Unknown), + 0u32, + builtin#lang(Count::Implied), + builtin#lang(Count::Implied), + ), + ], + ) + } + }; + }"#]] + .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT)) +} + #[test] fn test_macro_hygiene() { let (db, body, def) = lower( @@ -295,29 +381,31 @@ impl SsrError { expect![[r#" fn main() { _ = ra_test_fixture::error::SsrError::new( - builtin#lang(Arguments::new_v1_formatted)( - &[ - "Failed to resolve path `", "`", - ], - &[ + { + let args = [ builtin#lang(Argument::new_display)( &node.text(), ), - ], - &[ - builtin#lang(Placeholder::new)( - 0usize, - ' ', - builtin#lang(Alignment::Unknown), - 0u32, - builtin#lang(Count::Implied), - builtin#lang(Count::Implied), - ), - ], + ]; unsafe { - builtin#lang(UnsafeArg::new)() - }, - ), + builtin#lang(Arguments::new_v1_formatted)( + &[ + "Failed to resolve path `", "`", + ], + &args, + &[ + builtin#lang(Placeholder::new)( + 0usize, + ' ', + builtin#lang(Alignment::Unknown), + 0u32, + builtin#lang(Count::Implied), + builtin#lang(Count::Implied), + ), + ], + ) + } + }, ); }"#]] .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT)) @@ -327,7 +415,7 @@ impl SsrError { fn regression_10300() { let (db, body, def) = lower( r#" -//- minicore: concat, panic +//- minicore: concat, panic, fmt_before_1_89_0 mod private { pub use core::concat; } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs index bb0b70bc5bf2..c7707378a5b3 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs @@ -189,8 +189,8 @@ fn f() { } "#, expect![[r#" - BlockIdLt { [salsa id]: Id(3c01) } in BlockRelativeModuleId { block: Some(BlockIdLt { [salsa id]: Id(3c00) }), local_id: Idx::(1) } - BlockIdLt { [salsa id]: Id(3c00) } in BlockRelativeModuleId { block: None, local_id: Idx::(0) } + BlockId(3c01) in BlockRelativeModuleId { block: Some(BlockId(3c00)), local_id: Idx::(1) } + BlockId(3c00) in BlockRelativeModuleId { block: None, local_id: Idx::(0) } crate scope "#]], ); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index a542214d3031..a562f2d0af2f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -384,26 +384,7 @@ pub struct BlockLoc { /// The containing module. pub module: ModuleId, } -#[salsa_macros::tracked(debug)] -#[derive(PartialOrd, Ord)] -pub struct BlockIdLt<'db> { - pub loc: BlockLoc, -} -pub type BlockId = BlockIdLt<'static>; -impl hir_expand::Intern for BlockLoc { - type Database = dyn DefDatabase; - type ID = BlockId; - fn intern(self, db: &Self::Database) -> Self::ID { - unsafe { std::mem::transmute::, BlockId>(BlockIdLt::new(db, self)) } - } -} -impl hir_expand::Lookup for BlockId { - type Database = dyn DefDatabase; - type Data = BlockLoc; - fn lookup(&self, db: &Self::Database) -> Self::Data { - self.loc(db) - } -} +impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block); /// A `ModuleId` that is always a crate's root module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index d1432cacf8d8..b756bb859d3e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -1230,11 +1230,15 @@ impl InferenceContext<'_> { self.select_from_expr(*expr); } } + Expr::Let { pat: _, expr } => { + self.walk_expr(*expr); + let place = self.place_of_expr(*expr); + self.ref_expr(*expr, place); + } Expr::UnaryOp { expr, op: _ } | Expr::Array(Array::Repeat { initializer: expr, repeat: _ }) | Expr::Await { expr } | Expr::Loop { body: expr, label: _ } - | Expr::Let { pat: _, expr } | Expr::Box { expr } | Expr::Cast { expr, type_ref: _ } => { self.consume_expr(*expr); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index c253fe25672f..c58bd1b773e2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -268,7 +268,7 @@ pub fn layout_of_ty_query( // let pointee = tcx.normalize_erasing_regions(param_env, pointee); // if pointee.is_sized(tcx.at(DUMMY_SP), param_env) { - // return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); + // return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr))); // } let mut unsized_part = struct_tail_erasing_lifetimes(db, pointee.clone()); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs index 88d21be81ea6..7fb981752de8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs @@ -444,3 +444,22 @@ fn main() { expect!["99..165;49..54;120..121,133..134 ByRef(Mut { kind: Default }) a &'? mut A"], ); } + +#[test] +fn let_binding_is_a_ref_capture() { + check_closure_captures( + r#" +//- minicore:copy +struct S; +fn main() { + let mut s = S; + let s_ref = &mut s; + let closure = || { + if let ref cb = s_ref { + } + }; +} +"#, + expect!["83..135;49..54;112..117 ByRef(Shared) s_ref &'? &'? mut S"], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs index b1cf30b98f5b..0bce69a179b8 100644 --- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs @@ -242,9 +242,9 @@ fn resolve_assoc_or_field( resolve_field(db, variant_def, name, ns) } -fn resolve_assoc_item( - db: &dyn HirDatabase, - ty: &Type, +fn resolve_assoc_item<'db>( + db: &'db dyn HirDatabase, + ty: &Type<'db>, name: &Name, ns: Option, ) -> Option { @@ -256,10 +256,10 @@ fn resolve_assoc_item( }) } -fn resolve_impl_trait_item( - db: &dyn HirDatabase, +fn resolve_impl_trait_item<'db>( + db: &'db dyn HirDatabase, resolver: Resolver<'_>, - ty: &Type, + ty: &Type<'db>, name: &Name, ns: Option, ) -> Option { diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index f7b140e03d43..074bde91fb69 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -36,15 +36,15 @@ pub use hir_ty::{ }; macro_rules! diagnostics { - ($($diag:ident,)*) => { + ($($diag:ident $(<$lt:lifetime>)?,)*) => { #[derive(Debug)] - pub enum AnyDiagnostic {$( - $diag(Box<$diag>), + pub enum AnyDiagnostic<'db> {$( + $diag(Box<$diag $(<$lt>)?>), )*} $( - impl From<$diag> for AnyDiagnostic { - fn from(d: $diag) -> AnyDiagnostic { + impl<'db> From<$diag $(<$lt>)?> for AnyDiagnostic<'db> { + fn from(d: $diag $(<$lt>)?) -> AnyDiagnostic<'db> { AnyDiagnostic::$diag(Box::new(d)) } } @@ -69,12 +69,12 @@ macro_rules! diagnostics { diagnostics![ AwaitOutsideOfAsync, BreakOutsideOfLoop, - CastToUnsized, - ExpectedFunction, + CastToUnsized<'db>, + ExpectedFunction<'db>, InactiveCode, IncoherentImpl, IncorrectCase, - InvalidCast, + InvalidCast<'db>, InvalidDeriveTarget, MacroDefError, MacroError, @@ -85,7 +85,7 @@ diagnostics![ MissingFields, MissingMatchArms, MissingUnsafe, - MovedOutOfRef, + MovedOutOfRef<'db>, NeedMut, NonExhaustiveLet, NoSuchField, @@ -98,17 +98,17 @@ diagnostics![ TraitImplMissingAssocItems, TraitImplOrphan, TraitImplRedundantAssocItems, - TypedHole, - TypeMismatch, + TypedHole<'db>, + TypeMismatch<'db>, UndeclaredLabel, UnimplementedBuiltinMacro, UnreachableLabel, UnresolvedAssocItem, UnresolvedExternCrate, - UnresolvedField, + UnresolvedField<'db>, UnresolvedImport, UnresolvedMacroCall, - UnresolvedMethodCall, + UnresolvedMethodCall<'db>, UnresolvedModule, UnresolvedIdent, UnusedMut, @@ -130,9 +130,9 @@ pub struct BreakOutsideOfLoop { } #[derive(Debug)] -pub struct TypedHole { +pub struct TypedHole<'db> { pub expr: InFile, - pub expected: Type, + pub expected: Type<'db>, } #[derive(Debug)] @@ -242,25 +242,25 @@ pub struct MismatchedTupleStructPatArgCount { } #[derive(Debug)] -pub struct ExpectedFunction { +pub struct ExpectedFunction<'db> { pub call: InFile, - pub found: Type, + pub found: Type<'db>, } #[derive(Debug)] -pub struct UnresolvedField { +pub struct UnresolvedField<'db> { pub expr: InFile, - pub receiver: Type, + pub receiver: Type<'db>, pub name: Name, pub method_with_same_name_exists: bool, } #[derive(Debug)] -pub struct UnresolvedMethodCall { +pub struct UnresolvedMethodCall<'db> { pub expr: InFile, - pub receiver: Type, + pub receiver: Type<'db>, pub name: Name, - pub field_with_same_name: Option, + pub field_with_same_name: Option>, pub assoc_func_with_same_name: Option, } @@ -329,10 +329,10 @@ pub struct NonExhaustiveLet { } #[derive(Debug)] -pub struct TypeMismatch { +pub struct TypeMismatch<'db> { pub expr_or_pat: InFile, - pub expected: Type, - pub actual: Type, + pub expected: Type<'db>, + pub actual: Type<'db>, } #[derive(Debug)] @@ -352,8 +352,8 @@ pub struct UnusedVariable { } #[derive(Debug)] -pub struct MovedOutOfRef { - pub ty: Type, +pub struct MovedOutOfRef<'db> { + pub ty: Type<'db>, pub span: InFile, } @@ -403,17 +403,17 @@ pub struct RemoveUnnecessaryElse { } #[derive(Debug)] -pub struct CastToUnsized { +pub struct CastToUnsized<'db> { pub expr: InFile, - pub cast_ty: Type, + pub cast_ty: Type<'db>, } #[derive(Debug)] -pub struct InvalidCast { +pub struct InvalidCast<'db> { pub expr: InFile, pub error: CastError, - pub expr_ty: Type, - pub cast_ty: Type, + pub expr_ty: Type<'db>, + pub cast_ty: Type<'db>, } #[derive(Debug)] @@ -482,12 +482,12 @@ pub struct IncorrectGenericsOrder { pub expected_kind: GenericArgKind, } -impl AnyDiagnostic { +impl<'db> AnyDiagnostic<'db> { pub(crate) fn body_validation_diagnostic( - db: &dyn HirDatabase, + db: &'db dyn HirDatabase, diagnostic: BodyValidationDiagnostic, source_map: &hir_def::expr_store::BodySourceMap, - ) -> Option { + ) -> Option> { match diagnostic { BodyValidationDiagnostic::RecordMissingFields { record, variant, missed_fields } => { let variant_data = variant.variant_data(db); @@ -618,12 +618,12 @@ impl AnyDiagnostic { } pub(crate) fn inference_diagnostic( - db: &dyn HirDatabase, + db: &'db dyn HirDatabase, def: DefWithBodyId, d: &InferenceDiagnostic, source_map: &hir_def::expr_store::BodySourceMap, sig_map: &hir_def::expr_store::ExpressionStoreSourceMap, - ) -> Option { + ) -> Option> { let expr_syntax = |expr| { source_map .expr_syntax(expr) @@ -819,7 +819,7 @@ impl AnyDiagnostic { fn path_diagnostic( diag: &PathLoweringDiagnostic, path: InFile, - ) -> Option { + ) -> Option> { Some(match *diag { PathLoweringDiagnostic::GenericArgsProhibited { segment, reason } => { let segment = hir_segment_to_ast_segment(&path.value, segment)?; @@ -912,8 +912,8 @@ impl AnyDiagnostic { pub(crate) fn ty_diagnostic( diag: &TyLoweringDiagnostic, source_map: &ExpressionStoreSourceMap, - db: &dyn HirDatabase, - ) -> Option { + db: &'db dyn HirDatabase, + ) -> Option> { let Ok(source) = source_map.type_syntax(diag.source) else { stdx::never!("error on synthetic type syntax"); return None; diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs index 124ab8e274af..112558bdd04a 100644 --- a/src/tools/rust-analyzer/crates/hir/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir/src/display.rs @@ -431,7 +431,7 @@ impl HirDisplay for Variant { } } -impl HirDisplay for Type { +impl HirDisplay for Type<'_> { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { self.ty.hir_fmt(f) } @@ -743,7 +743,7 @@ impl HirDisplay for Static { } } -impl HirDisplay for TraitRef { +impl HirDisplay for TraitRef<'_> { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { self.trait_ref.hir_fmt(f) } diff --git a/src/tools/rust-analyzer/crates/hir/src/has_source.rs b/src/tools/rust-analyzer/crates/hir/src/has_source.rs index fe7429c86725..4767d4792e71 100644 --- a/src/tools/rust-analyzer/crates/hir/src/has_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/has_source.rs @@ -225,7 +225,7 @@ impl HasSource for LocalSource { } } -impl HasSource for Param { +impl HasSource for Param<'_> { type Ast = Either; fn source(self, db: &dyn HirDatabase) -> Option> { diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index adae335627ba..3b39707cf609 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -84,7 +84,7 @@ use nameres::diagnostics::DefDiagnosticKind; use rustc_hash::FxHashSet; use smallvec::SmallVec; use span::{AstIdNode, Edition, FileId}; -use stdx::{format_to, impl_from, never}; +use stdx::{format_to, impl_from, never, variance::PhantomCovariantLifetime}; use syntax::{ AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, T, TextRange, ToSmolStr, ast::{self, HasAttrs as _, HasName, HasVisibility as _}, @@ -400,7 +400,11 @@ impl ModuleDef { Some(name) } - pub fn diagnostics(self, db: &dyn HirDatabase, style_lints: bool) -> Vec { + pub fn diagnostics<'db>( + self, + db: &'db dyn HirDatabase, + style_lints: bool, + ) -> Vec> { let id = match self { ModuleDef::Adt(it) => match it { Adt::Struct(it) => it.id.into(), @@ -612,10 +616,10 @@ impl Module { } /// Fills `acc` with the module's diagnostics. - pub fn diagnostics( + pub fn diagnostics<'db>( self, - db: &dyn HirDatabase, - acc: &mut Vec, + db: &'db dyn HirDatabase, + acc: &mut Vec>, style_lints: bool, ) { let _p = tracing::info_span!("diagnostics", name = ?self.name(db)).entered(); @@ -970,10 +974,10 @@ impl Module { } } -fn macro_call_diagnostics( - db: &dyn HirDatabase, +fn macro_call_diagnostics<'db>( + db: &'db dyn HirDatabase, macro_call_id: MacroCallId, - acc: &mut Vec, + acc: &mut Vec>, ) { let Some(e) = db.parse_macro_expansion_error(macro_call_id) else { return; @@ -1010,7 +1014,11 @@ fn macro_call_diagnostics( } } -fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec, m: Macro) { +fn emit_macro_def_diagnostics<'db>( + db: &'db dyn HirDatabase, + acc: &mut Vec>, + m: Macro, +) { let id = db.macro_def(m.id); if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_expander(id) { if let Some(e) = expander.mac.err() { @@ -1030,18 +1038,18 @@ fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec } } -fn emit_def_diagnostic( - db: &dyn HirDatabase, - acc: &mut Vec, +fn emit_def_diagnostic<'db>( + db: &'db dyn HirDatabase, + acc: &mut Vec>, diag: &DefDiagnostic, edition: Edition, ) { emit_def_diagnostic_(db, acc, &diag.kind, edition) } -fn emit_def_diagnostic_( - db: &dyn HirDatabase, - acc: &mut Vec, +fn emit_def_diagnostic_<'db>( + db: &'db dyn HirDatabase, + acc: &mut Vec>, diag: &DefDiagnosticKind, edition: Edition, ) { @@ -1251,14 +1259,18 @@ impl TupleField { Name::new_tuple_field(self.index as usize) } - pub fn ty(&self, db: &dyn HirDatabase) -> Type { + pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> { let ty = db.infer(self.owner).tuple_field_access_types[&self.tuple] .as_slice(Interner) .get(self.index as usize) .and_then(|arg| arg.ty(Interner)) .cloned() .unwrap_or_else(|| TyKind::Error.intern(Interner)); - Type { env: db.trait_environment_for_body(self.owner), ty } + Type { + env: db.trait_environment_for_body(self.owner), + ty, + _pd: PhantomCovariantLifetime::new(), + } } } @@ -1309,7 +1321,7 @@ impl Field { /// Returns the type as in the signature of the struct (i.e., with /// placeholder types for type parameters). Only use this in the context of /// the field definition. - pub fn ty(&self, db: &dyn HirDatabase) -> Type { + pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> { let var_id = self.parent.into(); let generic_def_id: GenericDefId = match self.parent { VariantDef::Struct(it) => it.id.into(), @@ -1322,7 +1334,11 @@ impl Field { } // FIXME: Find better API to also handle const generics - pub fn ty_with_args(&self, db: &dyn HirDatabase, generics: impl Iterator) -> Type { + pub fn ty_with_args<'db>( + &self, + db: &'db dyn HirDatabase, + generics: impl Iterator>, + ) -> Type<'db> { let var_id = self.parent.into(); let def_id: AdtId = match self.parent { VariantDef::Struct(it) => it.id.into(), @@ -1394,15 +1410,15 @@ impl Struct { .collect() } - pub fn ty(self, db: &dyn HirDatabase) -> Type { + pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { Type::from_def(db, self.id) } - pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type { + pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type<'_> { Type::from_def_placeholders(db, self.id) } - pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type { + pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> { Type::from_value_def(db, self.id) } @@ -1449,15 +1465,15 @@ impl Union { Module { id: self.id.lookup(db).container } } - pub fn ty(self, db: &dyn HirDatabase) -> Type { + pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { Type::from_def(db, self.id) } - pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type { + pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type<'_> { Type::from_def_placeholders(db, self.id) } - pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type { + pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> { Type::from_value_def(db, self.id) } @@ -1515,16 +1531,16 @@ impl Enum { db.enum_signature(self.id).repr } - pub fn ty(self, db: &dyn HirDatabase) -> Type { + pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { Type::from_def(db, self.id) } - pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type { + pub fn ty_placeholders<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { Type::from_def_placeholders(db, self.id) } /// The type of the enum variant bodies. - pub fn variant_body_ty(self, db: &dyn HirDatabase) -> Type { + pub fn variant_body_ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { Type::new_for_crate( self.id.lookup(db).container.krate(), TyBuilder::builtin(match db.enum_signature(self.id).variant_body_type() { @@ -1599,7 +1615,7 @@ impl Variant { self.id.lookup(db).parent.into() } - pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type { + pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> { Type::from_value_def(db, self.id) } @@ -1701,14 +1717,18 @@ impl Adt { /// Turns this ADT into a type. Any type parameters of the ADT will be /// turned into unknown types, which is good for e.g. finding the most /// general set of completions, but will not look very nice when printed. - pub fn ty(self, db: &dyn HirDatabase) -> Type { + pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { let id = AdtId::from(self); Type::from_def(db, id) } /// Turns this ADT into a type with the given type parameters. This isn't /// the greatest API, FIXME find a better one. - pub fn ty_with_args(self, db: &dyn HirDatabase, args: impl Iterator) -> Type { + pub fn ty_with_args<'db>( + self, + db: &'db dyn HirDatabase, + args: impl Iterator>, + ) -> Type<'db> { let id = AdtId::from(self); let mut it = args.map(|t| t.ty); let ty = TyBuilder::def_ty(db, id.into(), None) @@ -1841,7 +1861,7 @@ impl DefWithBody { } /// Returns the type this def's body has to evaluate to. - pub fn body_type(self, db: &dyn HirDatabase) -> Type { + pub fn body_type(self, db: &dyn HirDatabase) -> Type<'_> { match self { DefWithBody::Function(it) => it.ret_type(db), DefWithBody::Static(it) => it.ty(db), @@ -1874,10 +1894,10 @@ impl DefWithBody { } } - pub fn diagnostics( + pub fn diagnostics<'db>( self, - db: &dyn HirDatabase, - acc: &mut Vec, + db: &'db dyn HirDatabase, + acc: &mut Vec>, style_lints: bool, ) { let krate = self.module(db).id.krate(); @@ -2107,7 +2127,7 @@ impl DefWithBody { fn expr_store_diagnostics( db: &dyn HirDatabase, - acc: &mut Vec, + acc: &mut Vec>, source_map: &ExpressionStoreSourceMap, ) { for diag in source_map.diagnostics() { @@ -2172,11 +2192,11 @@ impl Function { db.function_signature(self.id).name.clone() } - pub fn ty(self, db: &dyn HirDatabase) -> Type { + pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { Type::from_value_def(db, self.id) } - pub fn fn_ptr_type(self, db: &dyn HirDatabase) -> Type { + pub fn fn_ptr_type(self, db: &dyn HirDatabase) -> Type<'_> { let resolver = self.id.resolver(db); let substs = TyBuilder::placeholder_subst(db, self.id); let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs); @@ -2185,7 +2205,7 @@ impl Function { } /// Get this function's return type - pub fn ret_type(self, db: &dyn HirDatabase) -> Type { + pub fn ret_type(self, db: &dyn HirDatabase) -> Type<'_> { let resolver = self.id.resolver(db); let substs = TyBuilder::placeholder_subst(db, self.id); let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs); @@ -2194,11 +2214,11 @@ impl Function { } // FIXME: Find better API to also handle const generics - pub fn ret_type_with_args( + pub fn ret_type_with_args<'db>( self, - db: &dyn HirDatabase, - generics: impl Iterator, - ) -> Type { + db: &'db dyn HirDatabase, + generics: impl Iterator>, + ) -> Type<'db> { let resolver = self.id.resolver(db); let parent_id: Option = match self.id.lookup(db).container { ItemContainerId::ImplId(it) => Some(it.into()), @@ -2223,7 +2243,7 @@ impl Function { Type::new_with_resolver_inner(db, &resolver, ty) } - pub fn async_ret_type(self, db: &dyn HirDatabase) -> Option { + pub fn async_ret_type<'db>(self, db: &'db dyn HirDatabase) -> Option> { if !self.is_async(db) { return None; } @@ -2247,7 +2267,7 @@ impl Function { self.has_self_param(db).then_some(SelfParam { func: self.id }) } - pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec { + pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec> { let environment = db.trait_environment(self.id.into()); let substs = TyBuilder::placeholder_subst(db, self.id); let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs); @@ -2256,7 +2276,11 @@ impl Function { .iter() .enumerate() .map(|(idx, ty)| { - let ty = Type { env: environment.clone(), ty: ty.clone() }; + let ty = Type { + env: environment.clone(), + ty: ty.clone(), + _pd: PhantomCovariantLifetime::new(), + }; Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx } }) .collect() @@ -2266,12 +2290,12 @@ impl Function { db.function_signature(self.id).params.len() } - pub fn method_params(self, db: &dyn HirDatabase) -> Option> { + pub fn method_params(self, db: &dyn HirDatabase) -> Option>> { self.self_param(db)?; Some(self.params_without_self(db)) } - pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec { + pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec> { let environment = db.trait_environment(self.id.into()); let substs = TyBuilder::placeholder_subst(db, self.id); let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs); @@ -2282,18 +2306,22 @@ impl Function { .enumerate() .skip(skip) .map(|(idx, ty)| { - let ty = Type { env: environment.clone(), ty: ty.clone() }; + let ty = Type { + env: environment.clone(), + ty: ty.clone(), + _pd: PhantomCovariantLifetime::new(), + }; Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx } }) .collect() } // FIXME: Find better API to also handle const generics - pub fn params_without_self_with_args( + pub fn params_without_self_with_args<'db>( self, - db: &dyn HirDatabase, - generics: impl Iterator, - ) -> Vec { + db: &'db dyn HirDatabase, + generics: impl Iterator>, + ) -> Vec> { let environment = db.trait_environment(self.id.into()); let parent_id: Option = match self.id.lookup(db).container { ItemContainerId::ImplId(it) => Some(it.into()), @@ -2328,7 +2356,11 @@ impl Function { .enumerate() .skip(skip) .map(|(idx, ty)| { - let ty = Type { env: environment.clone(), ty: ty.clone() }; + let ty = Type { + env: environment.clone(), + ty: ty.clone(), + _pd: PhantomCovariantLifetime::new(), + }; Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx } }) .collect() @@ -2358,7 +2390,8 @@ impl Function { return true; } - let Some(impl_traits) = self.ret_type(db).as_impl_traits(db) else { return false }; + let ret_type = self.ret_type(db); + let Some(impl_traits) = ret_type.as_impl_traits(db) else { return false }; let Some(future_trait_id) = LangItem::Future.resolve_trait(db, self.ty(db).env.krate) else { return false; @@ -2501,14 +2534,14 @@ impl From for Access { } #[derive(Clone, PartialEq, Eq, Hash, Debug)] -pub struct Param { +pub struct Param<'db> { func: Callee, /// The index in parameter list, including self parameter. idx: usize, - ty: Type, + ty: Type<'db>, } -impl Param { +impl<'db> Param<'db> { pub fn parent_fn(&self) -> Option { match self.func { Callee::Def(CallableDefId::FunctionId(f)) => Some(f.into()), @@ -2524,7 +2557,7 @@ impl Param { self.idx } - pub fn ty(&self) -> &Type { + pub fn ty(&self) -> &Type<'db> { &self.ty } @@ -2591,17 +2624,21 @@ impl SelfParam { Function::from(self.func) } - pub fn ty(&self, db: &dyn HirDatabase) -> Type { + pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> { let substs = TyBuilder::placeholder_subst(db, self.func); let callable_sig = db.callable_item_signature(self.func.into()).substitute(Interner, &substs); let environment = db.trait_environment(self.func.into()); let ty = callable_sig.params()[0].clone(); - Type { env: environment, ty } + Type { env: environment, ty, _pd: PhantomCovariantLifetime::new() } } // FIXME: Find better API to also handle const generics - pub fn ty_with_args(&self, db: &dyn HirDatabase, generics: impl Iterator) -> Type { + pub fn ty_with_args<'db>( + &self, + db: &'db dyn HirDatabase, + generics: impl Iterator>, + ) -> Type<'db> { let parent_id: GenericDefId = match self.func.lookup(db).container { ItemContainerId::ImplId(it) => it.into(), ItemContainerId::TraitId(it) => it.into(), @@ -2626,7 +2663,7 @@ impl SelfParam { db.callable_item_signature(self.func.into()).substitute(Interner, &substs); let environment = db.trait_environment(self.func.into()); let ty = callable_sig.params()[0].clone(); - Type { env: environment, ty } + Type { env: environment, ty, _pd: PhantomCovariantLifetime::new() } } } @@ -2714,7 +2751,7 @@ impl Const { self.source(db)?.value.body() } - pub fn ty(self, db: &dyn HirDatabase) -> Type { + pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { Type::from_value_def(db, self.id) } @@ -2791,7 +2828,7 @@ impl Static { self.source(db)?.value.body() } - pub fn ty(self, db: &dyn HirDatabase) -> Type { + pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { Type::from_value_def(db, self.id) } @@ -2961,11 +2998,11 @@ impl TypeAlias { Module { id: self.id.module(db) } } - pub fn ty(self, db: &dyn HirDatabase) -> Type { + pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { Type::from_def(db, self.id) } - pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type { + pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type<'_> { Type::from_def_placeholders(db, self.id) } @@ -3010,7 +3047,7 @@ impl BuiltinType { BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str } } - pub fn ty(self, db: &dyn HirDatabase) -> Type { + pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { let core = Crate::core(db).map(|core| core.id).unwrap_or_else(|| db.all_crates()[0]); Type::new_for_crate(core, TyBuilder::builtin(self.inner)) } @@ -3472,7 +3509,7 @@ impl AssocItem { } } - pub fn implementing_ty(self, db: &dyn HirDatabase) -> Option { + pub fn implementing_ty(self, db: &dyn HirDatabase) -> Option> { match self.container(db) { AssocItemContainer::Impl(i) => Some(i.self_ty(db)), _ => None, @@ -3500,10 +3537,10 @@ impl AssocItem { } } - pub fn diagnostics( + pub fn diagnostics<'db>( self, - db: &dyn HirDatabase, - acc: &mut Vec, + db: &'db dyn HirDatabase, + acc: &mut Vec>, style_lints: bool, ) { match self { @@ -3625,7 +3662,7 @@ impl GenericDef { } } - pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec) { + pub fn diagnostics<'db>(self, db: &'db dyn HirDatabase, acc: &mut Vec>) { let def = self.id(); let generics = db.generic_params(def); @@ -3690,18 +3727,19 @@ impl GenericDef { // We cannot call this `Substitution` unfortunately... #[derive(Debug)] -pub struct GenericSubstitution { +pub struct GenericSubstitution<'db> { def: GenericDefId, subst: Substitution, env: Arc, + _pd: PhantomCovariantLifetime<'db>, } -impl GenericSubstitution { +impl<'db> GenericSubstitution<'db> { fn new(def: GenericDefId, subst: Substitution, env: Arc) -> Self { - Self { def, subst, env } + Self { def, subst, env, _pd: PhantomCovariantLifetime::new() } } - pub fn types(&self, db: &dyn HirDatabase) -> Vec<(Symbol, Type)> { + pub fn types(&self, db: &'db dyn HirDatabase) -> Vec<(Symbol, Type<'db>)> { let container = match self.def { GenericDefId::ConstId(id) => Some(id.lookup(db).container), GenericDefId::FunctionId(id) => Some(id.lookup(db).container), @@ -3744,7 +3782,10 @@ impl GenericSubstitution { container_params .chain(self_params) .filter_map(|(ty, name)| { - Some((name?.symbol().clone(), Type { ty, env: self.env.clone() })) + Some(( + name?.symbol().clone(), + Type { ty, env: self.env.clone(), _pd: PhantomCovariantLifetime::new() }, + )) }) .collect() } @@ -3847,7 +3888,7 @@ impl Local { self.parent(db).module(db) } - pub fn ty(self, db: &dyn HirDatabase) -> Type { + pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { let def = self.parent; let infer = db.infer(def); let ty = infer[self.binding_id].clone(); @@ -4109,6 +4150,10 @@ impl TypeParam { self.merge().name(db) } + pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef { + self.id.parent().into() + } + pub fn module(self, db: &dyn HirDatabase) -> Module { self.id.parent().module(db).into() } @@ -4124,7 +4169,7 @@ impl TypeParam { } } - pub fn ty(self, db: &dyn HirDatabase) -> Type { + pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { let resolver = self.id.parent().resolver(db); let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id.into())).intern(Interner); @@ -4146,7 +4191,7 @@ impl TypeParam { .collect() } - pub fn default(self, db: &dyn HirDatabase) -> Option { + pub fn default(self, db: &dyn HirDatabase) -> Option> { let ty = generic_arg_from_param(db, self.id.into())?; let resolver = self.id.parent().resolver(db); match ty.data(Interner) { @@ -4211,7 +4256,7 @@ impl ConstParam { self.id.parent().into() } - pub fn ty(self, db: &dyn HirDatabase) -> Type { + pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { Type::new(db, self.id.parent(), db.const_param_ty(self.id)) } @@ -4268,7 +4313,7 @@ impl TypeOrConstParam { } } - pub fn ty(self, db: &dyn HirDatabase) -> Type { + pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { match self.split(db) { Either::Left(it) => it.ty(db), Either::Right(it) => it.ty(db), @@ -4313,7 +4358,10 @@ impl Impl { module.id.def_map(db)[module.id.local_id].scope.impls().map(Into::into).collect() } - pub fn all_for_type(db: &dyn HirDatabase, Type { ty, env }: Type) -> Vec { + pub fn all_for_type<'db>( + db: &'db dyn HirDatabase, + Type { ty, env, _pd: _ }: Type<'db>, + ) -> Vec { let def_crates = match method_resolution::def_crates(db, &ty, env.krate) { Some(def_crates) => def_crates, None => return Vec::new(), @@ -4398,14 +4446,14 @@ impl Impl { Some(Trait { id }) } - pub fn trait_ref(self, db: &dyn HirDatabase) -> Option { + pub fn trait_ref(self, db: &dyn HirDatabase) -> Option> { let substs = TyBuilder::placeholder_subst(db, self.id); let trait_ref = db.impl_trait(self.id)?.substitute(Interner, &substs); let resolver = self.id.resolver(db); Some(TraitRef::new_with_resolver(db, &resolver, trait_ref)) } - pub fn self_ty(self, db: &dyn HirDatabase) -> Type { + pub fn self_ty(self, db: &dyn HirDatabase) -> Type<'_> { let resolver = self.id.resolver(db); let substs = TyBuilder::placeholder_subst(db, self.id); let ty = db.impl_self_ty(self.id).substitute(Interner, &substs); @@ -4467,21 +4515,22 @@ impl Impl { } #[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct TraitRef { +pub struct TraitRef<'db> { env: Arc, trait_ref: hir_ty::TraitRef, + _pd: PhantomCovariantLifetime<'db>, } -impl TraitRef { +impl<'db> TraitRef<'db> { pub(crate) fn new_with_resolver( - db: &dyn HirDatabase, + db: &'db dyn HirDatabase, resolver: &Resolver<'_>, trait_ref: hir_ty::TraitRef, - ) -> TraitRef { + ) -> Self { let env = resolver .generic_def() .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); - TraitRef { env, trait_ref } + TraitRef { env, trait_ref, _pd: PhantomCovariantLifetime::new() } } pub fn trait_(&self) -> Trait { @@ -4489,21 +4538,21 @@ impl TraitRef { Trait { id } } - pub fn self_ty(&self) -> Type { + pub fn self_ty(&self) -> Type<'_> { let ty = self.trait_ref.self_type_parameter(Interner); - Type { env: self.env.clone(), ty } + Type { env: self.env.clone(), ty, _pd: PhantomCovariantLifetime::new() } } /// Returns `idx`-th argument of this trait reference if it is a type argument. Note that the /// first argument is the `Self` type. - pub fn get_type_argument(&self, idx: usize) -> Option { + pub fn get_type_argument(&self, idx: usize) -> Option> { self.trait_ref .substitution .as_slice(Interner) .get(idx) .and_then(|arg| arg.ty(Interner)) .cloned() - .map(|ty| Type { env: self.env.clone(), ty }) + .map(|ty| Type { env: self.env.clone(), ty, _pd: PhantomCovariantLifetime::new() }) } } @@ -4551,7 +4600,7 @@ impl Closure { .collect() } - pub fn capture_types(&self, db: &dyn HirDatabase) -> Vec { + pub fn capture_types<'db>(&self, db: &'db dyn HirDatabase) -> Vec> { let owner = db.lookup_intern_closure((self.id).into()).0; let infer = &db.infer(owner); let (captures, _) = infer.closure_info(&self.id); @@ -4560,6 +4609,7 @@ impl Closure { .map(|capture| Type { env: db.trait_environment_for_body(owner), ty: capture.ty(&self.subst), + _pd: PhantomCovariantLifetime::new(), }) .collect() } @@ -4691,40 +4741,45 @@ impl CaptureUsageSource { } #[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct Type { +pub struct Type<'db> { env: Arc, ty: Ty, + _pd: PhantomCovariantLifetime<'db>, } -impl Type { - pub(crate) fn new_with_resolver(db: &dyn HirDatabase, resolver: &Resolver<'_>, ty: Ty) -> Type { +impl<'db> Type<'db> { + pub(crate) fn new_with_resolver( + db: &'db dyn HirDatabase, + resolver: &Resolver<'_>, + ty: Ty, + ) -> Self { Type::new_with_resolver_inner(db, resolver, ty) } pub(crate) fn new_with_resolver_inner( - db: &dyn HirDatabase, + db: &'db dyn HirDatabase, resolver: &Resolver<'_>, ty: Ty, - ) -> Type { + ) -> Self { let environment = resolver .generic_def() .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); - Type { env: environment, ty } + Type { env: environment, ty, _pd: PhantomCovariantLifetime::new() } } - pub(crate) fn new_for_crate(krate: base_db::Crate, ty: Ty) -> Type { - Type { env: TraitEnvironment::empty(krate), ty } + pub(crate) fn new_for_crate(krate: base_db::Crate, ty: Ty) -> Self { + Type { env: TraitEnvironment::empty(krate), ty, _pd: PhantomCovariantLifetime::new() } } - fn new(db: &dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty) -> Type { + fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty) -> Self { let resolver = lexical_env.resolver(db); let environment = resolver .generic_def() .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); - Type { env: environment, ty } + Type { env: environment, ty, _pd: PhantomCovariantLifetime::new() } } - fn from_def(db: &dyn HirDatabase, def: impl Into + HasResolver) -> Type { + fn from_def(db: &'db dyn HirDatabase, def: impl Into + HasResolver) -> Self { let ty = db.ty(def.into()); let substs = TyBuilder::unknown_subst( db, @@ -4737,7 +4792,10 @@ impl Type { Type::new(db, def, ty.substitute(Interner, &substs)) } - fn from_def_placeholders(db: &dyn HirDatabase, def: impl Into + HasResolver) -> Type { + fn from_def_placeholders( + db: &'db dyn HirDatabase, + def: impl Into + HasResolver, + ) -> Self { let ty = db.ty(def.into()); let substs = TyBuilder::placeholder_subst( db, @@ -4750,7 +4808,10 @@ impl Type { Type::new(db, def, ty.substitute(Interner, &substs)) } - fn from_value_def(db: &dyn HirDatabase, def: impl Into + HasResolver) -> Type { + fn from_value_def( + db: &'db dyn HirDatabase, + def: impl Into + HasResolver, + ) -> Self { let Some(ty) = db.value_ty(def.into()) else { return Type::new(db, def, TyKind::Error.intern(Interner)); }; @@ -4770,13 +4831,17 @@ impl Type { Type::new(db, def, ty.substitute(Interner, &substs)) } - pub fn new_slice(ty: Type) -> Type { - Type { env: ty.env, ty: TyBuilder::slice(ty.ty) } + pub fn new_slice(ty: Self) -> Self { + Type { env: ty.env, ty: TyBuilder::slice(ty.ty), _pd: PhantomCovariantLifetime::new() } } - pub fn new_tuple(krate: base_db::Crate, tys: &[Type]) -> Type { + pub fn new_tuple(krate: base_db::Crate, tys: &[Self]) -> Self { let tys = tys.iter().map(|it| it.ty.clone()); - Type { env: TraitEnvironment::empty(krate), ty: TyBuilder::tuple_with(tys) } + Type { + env: TraitEnvironment::empty(krate), + ty: TyBuilder::tuple_with(tys), + _pd: PhantomCovariantLifetime::new(), + } } pub fn is_unit(&self) -> bool { @@ -4803,7 +4868,7 @@ impl Type { matches!(self.ty.kind(Interner), TyKind::Ref(..)) } - pub fn contains_reference(&self, db: &dyn HirDatabase) -> bool { + pub fn contains_reference(&self, db: &'db dyn HirDatabase) -> bool { return go(db, self.env.krate, &self.ty); fn go(db: &dyn HirDatabase, krate: base_db::Crate, ty: &Ty) -> bool { @@ -4847,13 +4912,13 @@ impl Type { } } - pub fn as_reference(&self) -> Option<(Type, Mutability)> { + pub fn as_reference(&self) -> Option<(Type<'db>, Mutability)> { let (ty, _lt, m) = self.ty.as_reference()?; let m = Mutability::from_mutable(matches!(m, hir_ty::Mutability::Mut)); Some((self.derived(ty.clone()), m)) } - pub fn add_reference(&self, mutability: Mutability) -> Type { + pub fn add_reference(&self, mutability: Mutability) -> Self { let ty_mutability = match mutability { Mutability::Shared => hir_ty::Mutability::Not, Mutability::Mut => hir_ty::Mutability::Mut, @@ -4889,25 +4954,25 @@ impl Type { matches!(self.ty.kind(Interner), TyKind::Tuple(..)) } - pub fn remove_ref(&self) -> Option { + pub fn remove_ref(&self) -> Option> { match &self.ty.kind(Interner) { TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), _ => None, } } - pub fn as_slice(&self) -> Option { + pub fn as_slice(&self) -> Option> { match &self.ty.kind(Interner) { TyKind::Slice(ty) => Some(self.derived(ty.clone())), _ => None, } } - pub fn strip_references(&self) -> Type { + pub fn strip_references(&self) -> Self { self.derived(self.ty.strip_references().clone()) } - pub fn strip_reference(&self) -> Type { + pub fn strip_reference(&self) -> Self { self.derived(self.ty.strip_reference().clone()) } @@ -4918,7 +4983,7 @@ impl Type { /// Checks that particular type `ty` implements `std::future::IntoFuture` or /// `std::future::Future` and returns the `Output` associated type. /// This function is used in `.await` syntax completion. - pub fn into_future_output(&self, db: &dyn HirDatabase) -> Option { + pub fn into_future_output(&self, db: &'db dyn HirDatabase) -> Option> { let trait_ = LangItem::IntoFutureIntoFuture .resolve_function(db, self.env.krate) .and_then(|into_future_fn| { @@ -4940,13 +5005,13 @@ impl Type { } /// This does **not** resolve `IntoFuture`, only `Future`. - pub fn future_output(self, db: &dyn HirDatabase) -> Option { + pub fn future_output(self, db: &'db dyn HirDatabase) -> Option> { let future_output = LangItem::FutureOutput.resolve_type_alias(db, self.env.krate)?; self.normalize_trait_assoc_type(db, &[], future_output.into()) } /// This does **not** resolve `IntoIterator`, only `Iterator`. - pub fn iterator_item(self, db: &dyn HirDatabase) -> Option { + pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option> { let iterator_trait = LangItem::Iterator.resolve_trait(db, self.env.krate)?; let iterator_item = db .trait_items(iterator_trait) @@ -4954,7 +5019,7 @@ impl Type { self.normalize_trait_assoc_type(db, &[], iterator_item.into()) } - pub fn impls_iterator(self, db: &dyn HirDatabase) -> bool { + pub fn impls_iterator(self, db: &'db dyn HirDatabase) -> bool { let Some(iterator_trait) = LangItem::Iterator.resolve_trait(db, self.env.krate) else { return false; }; @@ -4964,7 +5029,7 @@ impl Type { } /// Resolves the projection `::IntoIter` and returns the resulting type - pub fn into_iterator_iter(self, db: &dyn HirDatabase) -> Option { + pub fn into_iterator_iter(self, db: &'db dyn HirDatabase) -> Option> { let trait_ = LangItem::IntoIterIntoIter.resolve_function(db, self.env.krate).and_then( |into_iter_fn| { let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?; @@ -4989,7 +5054,7 @@ impl Type { /// /// This function can be used to check if a particular type is callable, since FnOnce is a /// supertrait of Fn and FnMut, so all callable types implements at least FnOnce. - pub fn impls_fnonce(&self, db: &dyn HirDatabase) -> bool { + pub fn impls_fnonce(&self, db: &'db dyn HirDatabase) -> bool { let fnonce_trait = match FnTrait::FnOnce.get_id(db, self.env.krate) { Some(it) => it, None => return false, @@ -5001,7 +5066,7 @@ impl Type { } // FIXME: Find better API that also handles const generics - pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { + pub fn impls_trait(&self, db: &'db dyn HirDatabase, trait_: Trait, args: &[Type<'db>]) -> bool { let mut it = args.iter().map(|t| t.ty.clone()); let trait_ref = TyBuilder::trait_ref(db, trait_.id) .push(self.ty.clone()) @@ -5029,10 +5094,10 @@ impl Type { pub fn normalize_trait_assoc_type( &self, - db: &dyn HirDatabase, - args: &[Type], + db: &'db dyn HirDatabase, + args: &[Type<'db>], alias: TypeAlias, - ) -> Option { + ) -> Option> { let mut args = args.iter(); let trait_id = match alias.id.lookup(db).container { ItemContainerId::TraitId(id) => id, @@ -5056,14 +5121,14 @@ impl Type { if ty.is_unknown() { None } else { Some(self.derived(ty)) } } - pub fn is_copy(&self, db: &dyn HirDatabase) -> bool { + pub fn is_copy(&self, db: &'db dyn HirDatabase) -> bool { let Some(copy_trait) = LangItem::Copy.resolve_trait(db, self.env.krate) else { return false; }; self.impls_trait(db, copy_trait.into(), &[]) } - pub fn as_callable(&self, db: &dyn HirDatabase) -> Option { + pub fn as_callable(&self, db: &'db dyn HirDatabase) -> Option> { let callee = match self.ty.kind(Interner) { TyKind::Closure(id, subst) => Callee::Closure(*id, subst.clone()), TyKind::Function(_) => Callee::FnPtr, @@ -5117,7 +5182,7 @@ impl Type { matches!(self.ty.kind(Interner), TyKind::Array(..)) } - pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { + pub fn is_packed(&self, db: &'db dyn HirDatabase) -> bool { let adt_id = match *self.ty.kind(Interner) { TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, _ => return false, @@ -5134,7 +5199,7 @@ impl Type { matches!(self.ty.kind(Interner), TyKind::Raw(..)) } - pub fn remove_raw_ptr(&self) -> Option { + pub fn remove_raw_ptr(&self) -> Option> { if let TyKind::Raw(_, ty) = self.ty.kind(Interner) { Some(self.derived(ty.clone())) } else { @@ -5182,7 +5247,7 @@ impl Type { } } - pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { + pub fn fields(&self, db: &'db dyn HirDatabase) -> Vec<(Field, Self)> { let (variant_id, substs) = match self.ty.kind(Interner) { TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), substs) => ((*s).into(), substs), TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), substs) => ((*u).into(), substs), @@ -5199,7 +5264,7 @@ impl Type { .collect() } - pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec { + pub fn tuple_fields(&self, _db: &'db dyn HirDatabase) -> Vec { if let TyKind::Tuple(_, substs) = &self.ty.kind(Interner) { substs .iter(Interner) @@ -5210,7 +5275,7 @@ impl Type { } } - pub fn as_array(&self, db: &dyn HirDatabase) -> Option<(Type, usize)> { + pub fn as_array(&self, db: &'db dyn HirDatabase) -> Option<(Self, usize)> { if let TyKind::Array(ty, len) = &self.ty.kind(Interner) { try_const_usize(db, len).map(|it| (self.derived(ty.clone()), it as usize)) } else { @@ -5228,14 +5293,14 @@ impl Type { /// Returns types that this type dereferences to (including this type itself). The returned /// iterator won't yield the same type more than once even if the deref chain contains a cycle. - pub fn autoderef<'db>( + pub fn autoderef( &self, db: &'db dyn HirDatabase, - ) -> impl Iterator + use<'_, 'db> { + ) -> impl Iterator> + use<'_, 'db> { self.autoderef_(db).map(move |ty| self.derived(ty)) } - fn autoderef_(&self, db: &dyn HirDatabase) -> impl Iterator { + fn autoderef_(&self, db: &'db dyn HirDatabase) -> impl Iterator { // There should be no inference vars in types passed here let canonical = hir_ty::replace_errors_with_variables(&self.ty); autoderef(db, self.env.clone(), canonical) @@ -5245,7 +5310,7 @@ impl Type { // lifetime problems, because we need to borrow temp `CrateImplDefs`. pub fn iterate_assoc_items( &self, - db: &dyn HirDatabase, + db: &'db dyn HirDatabase, krate: Crate, mut callback: impl FnMut(AssocItem) -> Option, ) -> Option { @@ -5259,7 +5324,7 @@ impl Type { fn iterate_assoc_items_dyn( &self, - db: &dyn HirDatabase, + db: &'db dyn HirDatabase, krate: Crate, callback: &mut dyn FnMut(AssocItemId) -> bool, ) { @@ -5298,7 +5363,7 @@ impl Type { /// - "String" /// - "U" /// ``` - pub fn type_arguments(&self) -> impl Iterator + '_ { + pub fn type_arguments(&self) -> impl Iterator> + '_ { self.ty .strip_references() .as_adt() @@ -5368,7 +5433,7 @@ impl Type { pub fn iterate_method_candidates_with_traits( &self, - db: &dyn HirDatabase, + db: &'db dyn HirDatabase, scope: &SemanticsScope<'_>, traits_in_scope: &FxHashSet, with_local_impls: Option, @@ -5396,7 +5461,7 @@ impl Type { pub fn iterate_method_candidates( &self, - db: &dyn HirDatabase, + db: &'db dyn HirDatabase, scope: &SemanticsScope<'_>, with_local_impls: Option, name: Option<&Name>, @@ -5418,7 +5483,7 @@ impl Type { /// are considered inherent methods. pub fn iterate_method_candidates_split_inherent( &self, - db: &dyn HirDatabase, + db: &'db dyn HirDatabase, scope: &SemanticsScope<'_>, traits_in_scope: &FxHashSet, with_local_impls: Option, @@ -5486,7 +5551,7 @@ impl Type { #[tracing::instrument(skip_all, fields(name = ?name))] pub fn iterate_path_candidates( &self, - db: &dyn HirDatabase, + db: &'db dyn HirDatabase, scope: &SemanticsScope<'_>, traits_in_scope: &FxHashSet, with_local_impls: Option, @@ -5521,7 +5586,7 @@ impl Type { #[tracing::instrument(skip_all, fields(name = ?name))] pub fn iterate_path_candidates_split_inherent( &self, - db: &dyn HirDatabase, + db: &'db dyn HirDatabase, scope: &SemanticsScope<'_>, traits_in_scope: &FxHashSet, with_local_impls: Option, @@ -5584,10 +5649,10 @@ impl Type { /// If a type can be represented as `dyn Trait`, returns all traits accessible via this type, /// or an empty iterator otherwise. - pub fn applicable_inherent_traits<'a>( - &'a self, - db: &'a dyn HirDatabase, - ) -> impl Iterator + 'a { + pub fn applicable_inherent_traits( + &self, + db: &'db dyn HirDatabase, + ) -> impl Iterator { let _p = tracing::info_span!("applicable_inherent_traits").entered(); self.autoderef_(db) .filter_map(|ty| ty.dyn_trait()) @@ -5595,7 +5660,7 @@ impl Type { .map(Trait::from) } - pub fn env_traits<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator + 'a { + pub fn env_traits(&self, db: &'db dyn HirDatabase) -> impl Iterator { let _p = tracing::info_span!("env_traits").entered(); self.autoderef_(db) .filter(|ty| matches!(ty.kind(Interner), TyKind::Placeholder(_))) @@ -5607,10 +5672,7 @@ impl Type { .map(Trait::from) } - pub fn as_impl_traits( - &self, - db: &dyn HirDatabase, - ) -> Option + use<>> { + pub fn as_impl_traits(&self, db: &'db dyn HirDatabase) -> Option> { self.ty.impl_trait_bounds(db).map(|it| { it.into_iter().filter_map(|pred| match pred.skip_binders() { hir_ty::WhereClause::Implemented(trait_ref) => { @@ -5621,33 +5683,33 @@ impl Type { }) } - pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option { + pub fn as_associated_type_parent_trait(&self, db: &'db dyn HirDatabase) -> Option { self.ty.associated_type_parent_trait(db).map(Into::into) } - fn derived(&self, ty: Ty) -> Type { - Type { env: self.env.clone(), ty } + fn derived(&self, ty: Ty) -> Self { + Type { env: self.env.clone(), ty, _pd: PhantomCovariantLifetime::new() } } /// Visits every type, including generic arguments, in this type. `cb` is called with type /// itself first, and then with its generic arguments. - pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) { - fn walk_substs( - db: &dyn HirDatabase, - type_: &Type, + pub fn walk(&self, db: &'db dyn HirDatabase, mut cb: impl FnMut(Type<'db>)) { + fn walk_substs<'db>( + db: &'db dyn HirDatabase, + type_: &Type<'db>, substs: &Substitution, - cb: &mut impl FnMut(Type), + cb: &mut impl FnMut(Type<'db>), ) { for ty in substs.iter(Interner).filter_map(|a| a.ty(Interner)) { walk_type(db, &type_.derived(ty.clone()), cb); } } - fn walk_bounds( - db: &dyn HirDatabase, - type_: &Type, + fn walk_bounds<'db>( + db: &'db dyn HirDatabase, + type_: &Type<'db>, bounds: &[QuantifiedWhereClause], - cb: &mut impl FnMut(Type), + cb: &mut impl FnMut(Type<'db>), ) { for pred in bounds { if let WhereClause::Implemented(trait_ref) = pred.skip_binders() { @@ -5664,7 +5726,11 @@ impl Type { } } - fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { + fn walk_type<'db>( + db: &'db dyn HirDatabase, + type_: &Type<'db>, + cb: &mut impl FnMut(Type<'db>), + ) { let ty = type_.ty.strip_references(); match ty.kind(Interner) { TyKind::Adt(_, substs) => { @@ -5732,7 +5798,7 @@ impl Type { /// /// Note that we consider placeholder types to unify with everything. /// For example `Option` and `Option` unify although there is unresolved goal `T = U`. - pub fn could_unify_with(&self, db: &dyn HirDatabase, other: &Type) -> bool { + pub fn could_unify_with(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool { let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone())); hir_ty::could_unify(db, self.env.clone(), &tys) } @@ -5741,17 +5807,17 @@ impl Type { /// /// This means that placeholder types are not considered to unify if there are any bounds set on /// them. For example `Option` and `Option` do not unify as we cannot show that `T = U` - pub fn could_unify_with_deeply(&self, db: &dyn HirDatabase, other: &Type) -> bool { + pub fn could_unify_with_deeply(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool { let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone())); hir_ty::could_unify_deeply(db, self.env.clone(), &tys) } - pub fn could_coerce_to(&self, db: &dyn HirDatabase, to: &Type) -> bool { + pub fn could_coerce_to(&self, db: &'db dyn HirDatabase, to: &Type<'db>) -> bool { let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), to.ty.clone())); hir_ty::could_coerce(db, self.env.clone(), &tys) } - pub fn as_type_param(&self, db: &dyn HirDatabase) -> Option { + pub fn as_type_param(&self, db: &'db dyn HirDatabase) -> Option { match self.ty.kind(Interner) { TyKind::Placeholder(p) => Some(TypeParam { id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p)), @@ -5761,19 +5827,19 @@ impl Type { } /// Returns unique `GenericParam`s contained in this type. - pub fn generic_params(&self, db: &dyn HirDatabase) -> FxHashSet { + pub fn generic_params(&self, db: &'db dyn HirDatabase) -> FxHashSet { hir_ty::collect_placeholders(&self.ty, db) .into_iter() .map(|id| TypeOrConstParam { id }.split(db).either_into()) .collect() } - pub fn layout(&self, db: &dyn HirDatabase) -> Result { + pub fn layout(&self, db: &'db dyn HirDatabase) -> Result { db.layout_of_ty(self.ty.clone(), self.env.clone()) .map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap())) } - pub fn drop_glue(&self, db: &dyn HirDatabase) -> DropGlue { + pub fn drop_glue(&self, db: &'db dyn HirDatabase) -> DropGlue { db.has_drop_glue(self.ty.clone(), self.env.clone()) } } @@ -5800,8 +5866,8 @@ impl InlineAsmOperand { // FIXME: Document this #[derive(Debug)] -pub struct Callable { - ty: Type, +pub struct Callable<'db> { + ty: Type<'db>, sig: CallableSig, callee: Callee, /// Whether this is a method that was called with method call syntax. @@ -5825,7 +5891,7 @@ pub enum CallableKind { FnImpl(FnTrait), } -impl Callable { +impl<'db> Callable<'db> { pub fn kind(&self) -> CallableKind { match self.callee { Callee::Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()), @@ -5840,7 +5906,7 @@ impl Callable { Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_), } } - pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(SelfParam, Type)> { + pub fn receiver_param(&self, db: &'db dyn HirDatabase) -> Option<(SelfParam, Type<'db>)> { let func = match self.callee { Callee::Def(CallableDefId::FunctionId(it)) if self.is_bound_method => it, _ => return None, @@ -5851,7 +5917,7 @@ impl Callable { pub fn n_params(&self) -> usize { self.sig.params().len() - if self.is_bound_method { 1 } else { 0 } } - pub fn params(&self) -> Vec { + pub fn params(&self) -> Vec> { self.sig .params() .iter() @@ -5861,14 +5927,14 @@ impl Callable { .map(|(idx, ty)| Param { func: self.callee.clone(), idx, ty }) .collect() } - pub fn return_type(&self) -> Type { + pub fn return_type(&self) -> Type<'db> { self.ty.derived(self.sig.ret().clone()) } pub fn sig(&self) -> &CallableSig { &self.sig } - pub fn ty(&self) -> &Type { + pub fn ty(&self) -> &Type<'db> { &self.ty } } @@ -6070,9 +6136,9 @@ impl From for ScopeDef { } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Adjustment { - pub source: Type, - pub target: Type, +pub struct Adjustment<'db> { + pub source: Type<'db>, + pub target: Type<'db>, pub kind: Adjust, } @@ -6171,7 +6237,7 @@ impl HasCrate for TypeAlias { } } -impl HasCrate for Type { +impl HasCrate for Type<'_> { fn krate(&self, _db: &dyn HirDatabase) -> Crate { self.env.krate.into() } @@ -6325,9 +6391,9 @@ pub enum DocLinkDef { SelfType(Trait), } -fn push_ty_diagnostics( - db: &dyn HirDatabase, - acc: &mut Vec, +fn push_ty_diagnostics<'db>( + db: &'db dyn HirDatabase, + acc: &mut Vec>, diagnostics: Option>, source_map: &ExpressionStoreSourceMap, ) { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 10498958242a..d96975831e06 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -123,15 +123,15 @@ impl PathResolutionPerNs { } #[derive(Debug)] -pub struct TypeInfo { +pub struct TypeInfo<'db> { /// The original type of the expression or pattern. - pub original: Type, + pub original: Type<'db>, /// The adjusted type, if an adjustment happened. - pub adjusted: Option, + pub adjusted: Option>, } -impl TypeInfo { - pub fn original(self) -> Type { +impl<'db> TypeInfo<'db> { + pub fn original(self) -> Type<'db> { self.original } @@ -140,7 +140,7 @@ impl TypeInfo { } /// The adjusted type, or the original in case no adjustments occurred. - pub fn adjusted(self) -> Type { + pub fn adjusted(self) -> Type<'db> { self.adjusted.unwrap_or(self.original) } } @@ -1534,7 +1534,7 @@ impl<'db> SemanticsImpl<'db> { Some(Label { parent, label_id }) } - pub fn resolve_type(&self, ty: &ast::Type) -> Option { + pub fn resolve_type(&self, ty: &ast::Type) -> Option> { let analyze = self.analyze(ty.syntax())?; analyze.type_of_type(self.db, ty) } @@ -1553,7 +1553,7 @@ impl<'db> SemanticsImpl<'db> { } } - pub fn expr_adjustments(&self, expr: &ast::Expr) -> Option> { + pub fn expr_adjustments(&self, expr: &ast::Expr) -> Option>> { let mutability = |m| match m { hir_ty::Mutability::Not => Mutability::Shared, hir_ty::Mutability::Mut => Mutability::Mut, @@ -1596,13 +1596,13 @@ impl<'db> SemanticsImpl<'db> { }) } - pub fn type_of_expr(&self, expr: &ast::Expr) -> Option { + pub fn type_of_expr(&self, expr: &ast::Expr) -> Option> { self.analyze(expr.syntax())? .type_of_expr(self.db, expr) .map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced }) } - pub fn type_of_pat(&self, pat: &ast::Pat) -> Option { + pub fn type_of_pat(&self, pat: &ast::Pat) -> Option> { self.analyze(pat.syntax())? .type_of_pat(self.db, pat) .map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced }) @@ -1611,15 +1611,15 @@ impl<'db> SemanticsImpl<'db> { /// It also includes the changes that binding mode makes in the type. For example in /// `let ref x @ Some(_) = None` the result of `type_of_pat` is `Option` but the result /// of this function is `&mut Option` - pub fn type_of_binding_in_pat(&self, pat: &ast::IdentPat) -> Option { + pub fn type_of_binding_in_pat(&self, pat: &ast::IdentPat) -> Option> { self.analyze(pat.syntax())?.type_of_binding_in_pat(self.db, pat) } - pub fn type_of_self(&self, param: &ast::SelfParam) -> Option { + pub fn type_of_self(&self, param: &ast::SelfParam) -> Option> { self.analyze(param.syntax())?.type_of_self(self.db, param) } - pub fn pattern_adjustments(&self, pat: &ast::Pat) -> SmallVec<[Type; 1]> { + pub fn pattern_adjustments(&self, pat: &ast::Pat) -> SmallVec<[Type<'db>; 1]> { self.analyze(pat.syntax()) .and_then(|it| it.pattern_adjustments(self.db, pat)) .unwrap_or_default() @@ -1629,7 +1629,7 @@ impl<'db> SemanticsImpl<'db> { self.analyze(pat.syntax())?.binding_mode_of_pat(self.db, pat) } - pub fn resolve_expr_as_callable(&self, call: &ast::Expr) -> Option { + pub fn resolve_expr_as_callable(&self, call: &ast::Expr) -> Option> { self.analyze(call.syntax())?.resolve_expr_as_callable(self.db, call) } @@ -1641,7 +1641,7 @@ impl<'db> SemanticsImpl<'db> { pub fn resolve_method_call_fallback( &self, call: &ast::MethodCallExpr, - ) -> Option<(Either, Option)> { + ) -> Option<(Either, Option>)> { self.analyze(call.syntax())?.resolve_method_call_fallback(self.db, call) } @@ -1649,10 +1649,10 @@ impl<'db> SemanticsImpl<'db> { // FIXME: better api for the trait environment pub fn resolve_trait_impl_method( &self, - env: Type, + env: Type<'db>, trait_: Trait, func: Function, - subst: impl IntoIterator, + subst: impl IntoIterator>, ) -> Option { let mut substs = hir_ty::TyBuilder::subst_for_def(self.db, TraitId::from(trait_), None); for s in subst { @@ -1691,7 +1691,10 @@ impl<'db> SemanticsImpl<'db> { // This does not resolve the method call to the correct trait impl! // We should probably fix that. - pub fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option { + pub fn resolve_method_call_as_callable( + &self, + call: &ast::MethodCallExpr, + ) -> Option> { self.analyze(call.syntax())?.resolve_method_call_as_callable(self.db, call) } @@ -1702,14 +1705,15 @@ impl<'db> SemanticsImpl<'db> { pub fn resolve_field_fallback( &self, field: &ast::FieldExpr, - ) -> Option<(Either, Function>, Option)> { + ) -> Option<(Either, Function>, Option>)> + { self.analyze(field.syntax())?.resolve_field_fallback(self.db, field) } pub fn resolve_record_field( &self, field: &ast::RecordExprField, - ) -> Option<(Field, Option, Type)> { + ) -> Option<(Field, Option, Type<'db>)> { self.resolve_record_field_with_substitution(field) .map(|(field, local, ty, _)| (field, local, ty)) } @@ -1717,18 +1721,21 @@ impl<'db> SemanticsImpl<'db> { pub fn resolve_record_field_with_substitution( &self, field: &ast::RecordExprField, - ) -> Option<(Field, Option, Type, GenericSubstitution)> { + ) -> Option<(Field, Option, Type<'db>, GenericSubstitution<'db>)> { self.analyze(field.syntax())?.resolve_record_field(self.db, field) } - pub fn resolve_record_pat_field(&self, field: &ast::RecordPatField) -> Option<(Field, Type)> { + pub fn resolve_record_pat_field( + &self, + field: &ast::RecordPatField, + ) -> Option<(Field, Type<'db>)> { self.resolve_record_pat_field_with_subst(field).map(|(field, ty, _)| (field, ty)) } pub fn resolve_record_pat_field_with_subst( &self, field: &ast::RecordPatField, - ) -> Option<(Field, Type, GenericSubstitution)> { + ) -> Option<(Field, Type<'db>, GenericSubstitution<'db>)> { self.analyze(field.syntax())?.resolve_record_pat_field(self.db, field) } @@ -1801,7 +1808,7 @@ impl<'db> SemanticsImpl<'db> { pub fn resolve_path_with_subst( &self, path: &ast::Path, - ) -> Option<(PathResolution, Option)> { + ) -> Option<(PathResolution, Option>)> { self.analyze(path.syntax())?.resolve_path(self.db, path) } @@ -1812,7 +1819,7 @@ impl<'db> SemanticsImpl<'db> { pub fn resolve_offset_of_field( &self, name_ref: &ast::NameRef, - ) -> Option<(Either, GenericSubstitution)> { + ) -> Option<(Either, GenericSubstitution<'db>)> { self.analyze_no_infer(name_ref.syntax())?.resolve_offset_of_field(self.db, name_ref) } @@ -1834,13 +1841,19 @@ impl<'db> SemanticsImpl<'db> { self.analyze(pat.syntax())?.resolve_bind_pat_to_const(self.db, pat) } - pub fn record_literal_missing_fields(&self, literal: &ast::RecordExpr) -> Vec<(Field, Type)> { + pub fn record_literal_missing_fields( + &self, + literal: &ast::RecordExpr, + ) -> Vec<(Field, Type<'db>)> { self.analyze(literal.syntax()) .and_then(|it| it.record_literal_missing_fields(self.db, literal)) .unwrap_or_default() } - pub fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> { + pub fn record_pattern_missing_fields( + &self, + pattern: &ast::RecordPat, + ) -> Vec<(Field, Type<'db>)> { self.analyze(pattern.syntax()) .and_then(|it| it.record_pattern_missing_fields(self.db, pattern)) .unwrap_or_default() diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 3273358b78e9..48543ca581ff 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -257,7 +257,11 @@ impl<'db> SourceAnalyzer<'db> { infer.expr_adjustments.get(&expr_id).map(|v| &**v) } - pub(crate) fn type_of_type(&self, db: &'db dyn HirDatabase, ty: &ast::Type) -> Option { + pub(crate) fn type_of_type( + &self, + db: &'db dyn HirDatabase, + ty: &ast::Type, + ) -> Option> { let type_ref = self.type_id(ty)?; let ty = TyLoweringContext::new( db, @@ -277,7 +281,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, expr: &ast::Expr, - ) -> Option<(Type, Option)> { + ) -> Option<(Type<'db>, Option>)> { let expr_id = self.expr_id(expr.clone())?; let infer = self.infer()?; let coerced = expr_id @@ -293,7 +297,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, pat: &ast::Pat, - ) -> Option<(Type, Option)> { + ) -> Option<(Type<'db>, Option>)> { let expr_or_pat_id = self.pat_id(pat)?; let infer = self.infer()?; let coerced = match expr_or_pat_id { @@ -316,7 +320,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, pat: &ast::IdentPat, - ) -> Option { + ) -> Option> { let binding_id = self.binding_id_of_pat(pat)?; let infer = self.infer()?; let ty = infer[binding_id].clone(); @@ -328,7 +332,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, _param: &ast::SelfParam, - ) -> Option { + ) -> Option> { let binding = self.body()?.self_param?; let ty = self.infer()?[binding].clone(); Some(Type::new_with_resolver(db, &self.resolver, ty)) @@ -353,7 +357,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, pat: &ast::Pat, - ) -> Option> { + ) -> Option; 1]>> { let pat_id = self.pat_id(pat)?; let infer = self.infer()?; Some( @@ -370,7 +374,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, call: &ast::MethodCallExpr, - ) -> Option { + ) -> Option> { let expr_id = self.expr_id(call.clone().into())?.as_expr()?; let (func, substs) = self.infer()?.method_resolution(expr_id)?; let ty = db.value_ty(func.into())?.substitute(Interner, &substs); @@ -395,7 +399,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, call: &ast::MethodCallExpr, - ) -> Option<(Either, Option)> { + ) -> Option<(Either, Option>)> { let expr_id = self.expr_id(call.clone().into())?.as_expr()?; let inference_result = self.infer()?; match inference_result.method_resolution(expr_id) { @@ -419,7 +423,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, call: &ast::Expr, - ) -> Option { + ) -> Option> { let (orig, adjusted) = self.type_of_expr(db, &call.clone())?; adjusted.unwrap_or(orig).as_callable(db) } @@ -440,7 +444,7 @@ impl<'db> SourceAnalyzer<'db> { field_expr: ExprId, infer: &InferenceResult, db: &'db dyn HirDatabase, - ) -> Option { + ) -> Option> { let body = self.store()?; if let Expr::Field { expr: object_expr, name: _ } = body[field_expr] { let (adt, subst) = type_of_expr_including_adjust(infer, object_expr)?.as_adt()?; @@ -457,7 +461,8 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, field: &ast::FieldExpr, - ) -> Option<(Either, Function>, Option)> { + ) -> Option<(Either, Function>, Option>)> + { let (def, ..) = self.body_()?; let expr_id = self.expr_id(field.clone().into())?.as_expr()?; let inference_result = self.infer()?; @@ -680,7 +685,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, field: &ast::RecordExprField, - ) -> Option<(Field, Option, Type, GenericSubstitution)> { + ) -> Option<(Field, Option, Type<'db>, GenericSubstitution<'db>)> { let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?; let expr = ast::Expr::from(record_expr); let expr_id = self.store_sm()?.node_expr(InFile::new(self.file_id, &expr))?; @@ -724,7 +729,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, field: &ast::RecordPatField, - ) -> Option<(Field, Type, GenericSubstitution)> { + ) -> Option<(Field, Type<'db>, GenericSubstitution<'db>)> { let field_name = field.field_name()?.as_name(); let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?; let pat_id = self.pat_id(&record_pat.into())?; @@ -779,7 +784,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, name_ref: &ast::NameRef, - ) -> Option<(Either, GenericSubstitution)> { + ) -> Option<(Either, GenericSubstitution<'db>)> { let offset_of_expr = ast::OffsetOfExpr::cast(name_ref.syntax().parent()?)?; let container = offset_of_expr.ty()?; let container = self.type_of_type(db, &container)?; @@ -851,7 +856,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, path: &ast::Path, - ) -> Option<(PathResolution, Option)> { + ) -> Option<(PathResolution, Option>)> { let parent = path.syntax().parent(); let parent = || parent.clone(); @@ -1216,7 +1221,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, literal: &ast::RecordExpr, - ) -> Option> { + ) -> Option)>> { let body = self.store()?; let infer = self.infer()?; @@ -1239,7 +1244,7 @@ impl<'db> SourceAnalyzer<'db> { &self, db: &'db dyn HirDatabase, pattern: &ast::RecordPat, - ) -> Option> { + ) -> Option)>> { let body = self.store()?; let infer = self.infer()?; @@ -1258,7 +1263,7 @@ impl<'db> SourceAnalyzer<'db> { substs: &Substitution, variant: VariantId, missing_fields: Vec, - ) -> Vec<(Field, Type)> { + ) -> Vec<(Field, Type<'db>)> { let field_types = db.field_types(variant); missing_fields diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search.rs b/src/tools/rust-analyzer/crates/hir/src/term_search.rs index af72179305c8..4b354e640628 100644 --- a/src/tools/rust-analyzer/crates/hir/src/term_search.rs +++ b/src/tools/rust-analyzer/crates/hir/src/term_search.rs @@ -22,20 +22,20 @@ enum NewTypesKey { /// Helper enum to squash big number of alternative trees into `Many` variant as there is too many /// to take into account. #[derive(Debug)] -enum AlternativeExprs { +enum AlternativeExprs<'db> { /// There are few trees, so we keep track of them all - Few(FxHashSet), + Few(FxHashSet>), /// There are too many trees to keep track of Many, } -impl AlternativeExprs { +impl<'db> AlternativeExprs<'db> { /// Construct alternative trees /// /// # Arguments /// `threshold` - threshold value for many trees (more than that is many) /// `exprs` - expressions iterator - fn new(threshold: usize, exprs: impl Iterator) -> AlternativeExprs { + fn new(threshold: usize, exprs: impl Iterator>) -> AlternativeExprs<'db> { let mut it = AlternativeExprs::Few(Default::default()); it.extend_with_threshold(threshold, exprs); it @@ -45,7 +45,7 @@ impl AlternativeExprs { /// /// # Arguments /// `ty` - Type of expressions queried (this is used to give type to `Expr::Many`) - fn exprs(&self, ty: &Type) -> Vec { + fn exprs(&self, ty: &Type<'db>) -> Vec> { match self { AlternativeExprs::Few(exprs) => exprs.iter().cloned().collect(), AlternativeExprs::Many => vec![Expr::Many(ty.clone())], @@ -57,7 +57,7 @@ impl AlternativeExprs { /// # Arguments /// `threshold` - threshold value for many trees (more than that is many) /// `exprs` - expressions iterator - fn extend_with_threshold(&mut self, threshold: usize, exprs: impl Iterator) { + fn extend_with_threshold(&mut self, threshold: usize, exprs: impl Iterator>) { match self { AlternativeExprs::Few(tts) => { for it in exprs { @@ -88,20 +88,20 @@ impl AlternativeExprs { /// Both of them are to speed up the term search by leaving out types / ScopeDefs that likely do /// not produce any new results. #[derive(Default, Debug)] -struct LookupTable { +struct LookupTable<'db> { /// All the `Expr`s in "value" produce the type of "key" - data: FxHashMap, + data: FxHashMap, AlternativeExprs<'db>>, /// New types reached since last query by the `NewTypesKey` - new_types: FxHashMap>, + new_types: FxHashMap>>, /// Types queried but not present - types_wishlist: FxHashSet, + types_wishlist: FxHashSet>, /// Threshold to squash trees to `Many` many_threshold: usize, } -impl LookupTable { +impl<'db> LookupTable<'db> { /// Initialize lookup table - fn new(many_threshold: usize, goal: Type) -> Self { + fn new(many_threshold: usize, goal: Type<'db>) -> Self { let mut res = Self { many_threshold, ..Default::default() }; res.new_types.insert(NewTypesKey::ImplMethod, Vec::new()); res.new_types.insert(NewTypesKey::StructProjection, Vec::new()); @@ -110,7 +110,7 @@ impl LookupTable { } /// Find all `Expr`s that unify with the `ty` - fn find(&mut self, db: &dyn HirDatabase, ty: &Type) -> Option> { + fn find(&mut self, db: &'db dyn HirDatabase, ty: &Type<'db>) -> Option>> { let res = self .data .iter() @@ -135,7 +135,7 @@ impl LookupTable { /// /// For example if we have type `i32` in data and we query for `&i32` it map all the type /// trees we have for `i32` with `Expr::Reference` and returns them. - fn find_autoref(&mut self, db: &dyn HirDatabase, ty: &Type) -> Option> { + fn find_autoref(&mut self, db: &'db dyn HirDatabase, ty: &Type<'db>) -> Option>> { let res = self .data .iter() @@ -174,7 +174,7 @@ impl LookupTable { /// Note that the types have to be the same, unification is not enough as unification is not /// transitive. For example Vec and FxHashSet both unify with Iterator, /// but they clearly do not unify themselves. - fn insert(&mut self, ty: Type, exprs: impl Iterator) { + fn insert(&mut self, ty: Type<'db>, exprs: impl Iterator>) { match self.data.get_mut(&ty) { Some(it) => { it.extend_with_threshold(self.many_threshold, exprs); @@ -192,14 +192,14 @@ impl LookupTable { } /// Iterate all the reachable types - fn iter_types(&self) -> impl Iterator + '_ { + fn iter_types(&self) -> impl Iterator> + '_ { self.data.keys().cloned() } /// Query new types reached since last query by key /// /// Create new key if you wish to query it to avoid conflicting with existing queries. - fn new_types(&mut self, key: NewTypesKey) -> Vec { + fn new_types(&mut self, key: NewTypesKey) -> Vec> { match self.new_types.get_mut(&key) { Some(it) => std::mem::take(it), None => Vec::new(), @@ -207,20 +207,20 @@ impl LookupTable { } /// Types queried but not found - fn types_wishlist(&mut self) -> &FxHashSet { + fn types_wishlist(&mut self) -> &FxHashSet> { &self.types_wishlist } } /// Context for the `term_search` function #[derive(Debug)] -pub struct TermSearchCtx<'a, DB: HirDatabase> { +pub struct TermSearchCtx<'db, DB: HirDatabase> { /// Semantics for the program - pub sema: &'a Semantics<'a, DB>, + pub sema: &'db Semantics<'db, DB>, /// Semantic scope, captures context for the term search - pub scope: &'a SemanticsScope<'a>, + pub scope: &'db SemanticsScope<'db>, /// Target / expected output type - pub goal: Type, + pub goal: Type<'db>, /// Configuration for term search pub config: TermSearchConfig, } @@ -263,7 +263,7 @@ impl Default for TermSearchConfig { /// Note that there are usually more ways we can get to the `goal` type but some are discarded to /// reduce the memory consumption. It is also unlikely anyone is willing ti browse through /// thousands of possible responses so we currently take first 10 from every tactic. -pub fn term_search(ctx: &TermSearchCtx<'_, DB>) -> Vec { +pub fn term_search<'db, DB: HirDatabase>(ctx: &'db TermSearchCtx<'db, DB>) -> Vec> { let module = ctx.scope.module(); let mut defs = FxHashSet::default(); defs.insert(ScopeDef::ModuleDef(ModuleDef::Module(module))); @@ -285,7 +285,7 @@ pub fn term_search(ctx: &TermSearchCtx<'_, DB>) -> Vec { }; // Try trivial tactic first, also populates lookup table - let mut solutions: Vec = tactics::trivial(ctx, &defs, &mut lookup).collect(); + let mut solutions: Vec> = tactics::trivial(ctx, &defs, &mut lookup).collect(); // Use well known types tactic before iterations as it does not depend on other tactics solutions.extend(tactics::famous_types(ctx, &defs, &mut lookup)); solutions.extend(tactics::assoc_const(ctx, &defs, &mut lookup)); diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs b/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs index 78ee3b5aa683..843831948adc 100644 --- a/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs +++ b/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs @@ -59,7 +59,7 @@ fn mod_item_path_str( /// So in short it pretty much gives us a way to get type `Option` using the items we have in /// scope. #[derive(Debug, Clone, Eq, Hash, PartialEq)] -pub enum Expr { +pub enum Expr<'db> { /// Constant Const(Const), /// Static variable @@ -69,26 +69,31 @@ pub enum Expr { /// Constant generic parameter ConstParam(ConstParam), /// Well known type (such as `true` for bool) - FamousType { ty: Type, value: &'static str }, + FamousType { ty: Type<'db>, value: &'static str }, /// Function call (does not take self param) - Function { func: Function, generics: Vec, params: Vec }, + Function { func: Function, generics: Vec>, params: Vec> }, /// Method call (has self param) - Method { func: Function, generics: Vec, target: Box, params: Vec }, + Method { + func: Function, + generics: Vec>, + target: Box>, + params: Vec>, + }, /// Enum variant construction - Variant { variant: Variant, generics: Vec, params: Vec }, + Variant { variant: Variant, generics: Vec>, params: Vec> }, /// Struct construction - Struct { strukt: Struct, generics: Vec, params: Vec }, + Struct { strukt: Struct, generics: Vec>, params: Vec> }, /// Tuple construction - Tuple { ty: Type, params: Vec }, + Tuple { ty: Type<'db>, params: Vec> }, /// Struct field access - Field { expr: Box, field: Field }, + Field { expr: Box>, field: Field }, /// Passing type as reference (with `&`) - Reference(Box), + Reference(Box>), /// Indicates possibility of many different options that all evaluate to `ty` - Many(Type), + Many(Type<'db>), } -impl Expr { +impl<'db> Expr<'db> { /// Generate source code for type tree. /// /// Note that trait imports are not added to generated code. @@ -96,8 +101,8 @@ impl Expr { /// by `traits_used` method are also imported. pub fn gen_source_code( &self, - sema_scope: &SemanticsScope<'_>, - many_formatter: &mut dyn FnMut(&Type) -> String, + sema_scope: &SemanticsScope<'db>, + many_formatter: &mut dyn FnMut(&Type<'db>) -> String, cfg: ImportPathConfig, display_target: DisplayTarget, ) -> Result { @@ -298,7 +303,7 @@ impl Expr { /// Get type of the type tree. /// /// Same as getting the type of root node - pub fn ty(&self, db: &dyn HirDatabase) -> Type { + pub fn ty(&self, db: &'db dyn HirDatabase) -> Type<'db> { match self { Expr::Const(it) => it.ty(db), Expr::Static(it) => it.ty(db), diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs index bcff44fcd016..9df131f90e40 100644 --- a/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs @@ -40,11 +40,11 @@ use super::{LookupTable, NewTypesKey, TermSearchCtx}; /// /// _Note that there is no use of calling this tactic in every iteration as the output does not /// depend on the current state of `lookup`_ -pub(super) fn trivial<'a, DB: HirDatabase>( - ctx: &'a TermSearchCtx<'a, DB>, +pub(super) fn trivial<'a, 'lt, 'db, DB: HirDatabase>( + ctx: &'a TermSearchCtx<'db, DB>, defs: &'a FxHashSet, - lookup: &'a mut LookupTable, -) -> impl Iterator + 'a { + lookup: &'lt mut LookupTable<'db>, +) -> impl Iterator> + use<'a, 'db, 'lt, DB> { let db = ctx.sema.db; defs.iter().filter_map(|def| { let expr = match def { @@ -104,11 +104,11 @@ pub(super) fn trivial<'a, DB: HirDatabase>( /// /// _Note that there is no use of calling this tactic in every iteration as the output does not /// depend on the current state of `lookup`_ -pub(super) fn assoc_const<'a, DB: HirDatabase>( - ctx: &'a TermSearchCtx<'a, DB>, +pub(super) fn assoc_const<'a, 'lt, 'db, DB: HirDatabase>( + ctx: &'a TermSearchCtx<'db, DB>, defs: &'a FxHashSet, - lookup: &'a mut LookupTable, -) -> impl Iterator + 'a { + lookup: &'lt mut LookupTable<'db>, +) -> impl Iterator> + use<'a, 'db, 'lt, DB> { let db = ctx.sema.db; let module = ctx.scope.module(); @@ -152,12 +152,12 @@ pub(super) fn assoc_const<'a, DB: HirDatabase>( /// * `defs` - Set of items in scope at term search target location /// * `lookup` - Lookup table for types /// * `should_continue` - Function that indicates when to stop iterating -pub(super) fn data_constructor<'a, DB: HirDatabase>( - ctx: &'a TermSearchCtx<'a, DB>, +pub(super) fn data_constructor<'a, 'lt, 'db, DB: HirDatabase>( + ctx: &'a TermSearchCtx<'db, DB>, _defs: &'a FxHashSet, - lookup: &'a mut LookupTable, + lookup: &'lt mut LookupTable<'db>, should_continue: &'a dyn std::ops::Fn() -> bool, -) -> impl Iterator + 'a { +) -> impl Iterator> + use<'a, 'db, 'lt, DB> { let db = ctx.sema.db; let module = ctx.scope.module(); lookup @@ -199,14 +199,14 @@ pub(super) fn data_constructor<'a, DB: HirDatabase>( let generics: Vec<_> = ty.type_arguments().collect(); // Early exit if some param cannot be filled from lookup - let param_exprs: Vec> = fields + let param_exprs: Vec>> = fields .into_iter() .map(|field| lookup.find(db, &field.ty_with_args(db, generics.iter().cloned()))) .collect::>()?; // Note that we need special case for 0 param constructors because of multi cartesian // product - let exprs: Vec = if param_exprs.is_empty() { + let exprs: Vec> = if param_exprs.is_empty() { vec![Expr::Struct { strukt, generics, params: Vec::new() }] } else { param_exprs @@ -247,7 +247,7 @@ pub(super) fn data_constructor<'a, DB: HirDatabase>( .into_iter() .filter_map(|variant| { // Early exit if some param cannot be filled from lookup - let param_exprs: Vec> = variant + let param_exprs: Vec>> = variant .fields(db) .into_iter() .map(|field| { @@ -257,7 +257,7 @@ pub(super) fn data_constructor<'a, DB: HirDatabase>( // Note that we need special case for 0 param constructors because of multi cartesian // product - let variant_exprs: Vec = if param_exprs.is_empty() { + let variant_exprs: Vec> = if param_exprs.is_empty() { vec![Expr::Variant { variant, generics: generics.clone(), @@ -301,12 +301,12 @@ pub(super) fn data_constructor<'a, DB: HirDatabase>( /// * `defs` - Set of items in scope at term search target location /// * `lookup` - Lookup table for types /// * `should_continue` - Function that indicates when to stop iterating -pub(super) fn free_function<'a, DB: HirDatabase>( - ctx: &'a TermSearchCtx<'a, DB>, +pub(super) fn free_function<'a, 'lt, 'db, DB: HirDatabase>( + ctx: &'a TermSearchCtx<'db, DB>, defs: &'a FxHashSet, - lookup: &'a mut LookupTable, + lookup: &'lt mut LookupTable<'db>, should_continue: &'a dyn std::ops::Fn() -> bool, -) -> impl Iterator + 'a { +) -> impl Iterator> + use<'a, 'db, 'lt, DB> { let db = ctx.sema.db; let module = ctx.scope.module(); defs.iter() @@ -375,7 +375,7 @@ pub(super) fn free_function<'a, DB: HirDatabase>( } // Early exit if some param cannot be filled from lookup - let param_exprs: Vec> = it + let param_exprs: Vec>> = it .params_without_self_with_args(db, generics.iter().cloned()) .into_iter() .map(|field| { @@ -389,7 +389,7 @@ pub(super) fn free_function<'a, DB: HirDatabase>( // Note that we need special case for 0 param constructors because of multi cartesian // product - let fn_exprs: Vec = if param_exprs.is_empty() { + let fn_exprs: Vec> = if param_exprs.is_empty() { vec![Expr::Function { func: *it, generics, params: Vec::new() }] } else { param_exprs @@ -432,12 +432,12 @@ pub(super) fn free_function<'a, DB: HirDatabase>( /// * `defs` - Set of items in scope at term search target location /// * `lookup` - Lookup table for types /// * `should_continue` - Function that indicates when to stop iterating -pub(super) fn impl_method<'a, DB: HirDatabase>( - ctx: &'a TermSearchCtx<'a, DB>, +pub(super) fn impl_method<'a, 'lt, 'db, DB: HirDatabase>( + ctx: &'a TermSearchCtx<'db, DB>, _defs: &'a FxHashSet, - lookup: &'a mut LookupTable, + lookup: &'lt mut LookupTable<'db>, should_continue: &'a dyn std::ops::Fn() -> bool, -) -> impl Iterator + 'a { +) -> impl Iterator> + use<'a, 'db, 'lt, DB> { let db = ctx.sema.db; let module = ctx.scope.module(); lookup @@ -507,14 +507,14 @@ pub(super) fn impl_method<'a, DB: HirDatabase>( let target_type_exprs = lookup.find(db, &ty).expect("Type not in lookup"); // Early exit if some param cannot be filled from lookup - let param_exprs: Vec> = it + let param_exprs: Vec>> = it .params_without_self_with_args(db, ty.type_arguments()) .into_iter() .map(|field| lookup.find_autoref(db, field.ty())) .collect::>()?; let generics: Vec<_> = ty.type_arguments().collect(); - let fn_exprs: Vec = std::iter::once(target_type_exprs) + let fn_exprs: Vec> = std::iter::once(target_type_exprs) .chain(param_exprs) .multi_cartesian_product() .map(|params| { @@ -547,12 +547,12 @@ pub(super) fn impl_method<'a, DB: HirDatabase>( /// * `defs` - Set of items in scope at term search target location /// * `lookup` - Lookup table for types /// * `should_continue` - Function that indicates when to stop iterating -pub(super) fn struct_projection<'a, DB: HirDatabase>( - ctx: &'a TermSearchCtx<'a, DB>, +pub(super) fn struct_projection<'a, 'lt, 'db, DB: HirDatabase>( + ctx: &'a TermSearchCtx<'db, DB>, _defs: &'a FxHashSet, - lookup: &'a mut LookupTable, + lookup: &'lt mut LookupTable<'db>, should_continue: &'a dyn std::ops::Fn() -> bool, -) -> impl Iterator + 'a { +) -> impl Iterator> + use<'a, 'db, 'lt, DB> { let db = ctx.sema.db; let module = ctx.scope.module(); lookup @@ -589,11 +589,11 @@ pub(super) fn struct_projection<'a, DB: HirDatabase>( /// * `ctx` - Context for the term search /// * `defs` - Set of items in scope at term search target location /// * `lookup` - Lookup table for types -pub(super) fn famous_types<'a, DB: HirDatabase>( - ctx: &'a TermSearchCtx<'a, DB>, +pub(super) fn famous_types<'a, 'lt, 'db, DB: HirDatabase>( + ctx: &'a TermSearchCtx<'db, DB>, _defs: &'a FxHashSet, - lookup: &'a mut LookupTable, -) -> impl Iterator + 'a { + lookup: &'lt mut LookupTable<'db>, +) -> impl Iterator> + use<'a, 'db, 'lt, DB> { let db = ctx.sema.db; let module = ctx.scope.module(); [ @@ -620,12 +620,12 @@ pub(super) fn famous_types<'a, DB: HirDatabase>( /// * `defs` - Set of items in scope at term search target location /// * `lookup` - Lookup table for types /// * `should_continue` - Function that indicates when to stop iterating -pub(super) fn impl_static_method<'a, DB: HirDatabase>( - ctx: &'a TermSearchCtx<'a, DB>, +pub(super) fn impl_static_method<'a, 'lt, 'db, DB: HirDatabase>( + ctx: &'a TermSearchCtx<'db, DB>, _defs: &'a FxHashSet, - lookup: &'a mut LookupTable, + lookup: &'lt mut LookupTable<'db>, should_continue: &'a dyn std::ops::Fn() -> bool, -) -> impl Iterator + 'a { +) -> impl Iterator> + use<'a, 'db, 'lt, DB> { let db = ctx.sema.db; let module = ctx.scope.module(); lookup @@ -683,7 +683,7 @@ pub(super) fn impl_static_method<'a, DB: HirDatabase>( } // Early exit if some param cannot be filled from lookup - let param_exprs: Vec> = it + let param_exprs: Vec>> = it .params_without_self_with_args(db, ty.type_arguments()) .into_iter() .map(|field| lookup.find_autoref(db, field.ty())) @@ -692,7 +692,7 @@ pub(super) fn impl_static_method<'a, DB: HirDatabase>( // Note that we need special case for 0 param constructors because of multi cartesian // product let generics = ty.type_arguments().collect(); - let fn_exprs: Vec = if param_exprs.is_empty() { + let fn_exprs: Vec> = if param_exprs.is_empty() { vec![Expr::Function { func: it, generics, params: Vec::new() }] } else { param_exprs @@ -722,12 +722,12 @@ pub(super) fn impl_static_method<'a, DB: HirDatabase>( /// * `defs` - Set of items in scope at term search target location /// * `lookup` - Lookup table for types /// * `should_continue` - Function that indicates when to stop iterating -pub(super) fn make_tuple<'a, DB: HirDatabase>( - ctx: &'a TermSearchCtx<'a, DB>, +pub(super) fn make_tuple<'a, 'lt, 'db, DB: HirDatabase>( + ctx: &'a TermSearchCtx<'db, DB>, _defs: &'a FxHashSet, - lookup: &'a mut LookupTable, + lookup: &'lt mut LookupTable<'db>, should_continue: &'a dyn std::ops::Fn() -> bool, -) -> impl Iterator + 'a { +) -> impl Iterator> + use<'a, 'db, 'lt, DB> { let db = ctx.sema.db; let module = ctx.scope.module(); @@ -749,15 +749,15 @@ pub(super) fn make_tuple<'a, DB: HirDatabase>( } // Early exit if some param cannot be filled from lookup - let param_exprs: Vec> = + let param_exprs: Vec>> = ty.type_arguments().map(|field| lookup.find(db, &field)).collect::>()?; - let exprs: Vec = param_exprs + let exprs: Vec> = param_exprs .into_iter() .multi_cartesian_product() .filter(|_| should_continue()) .map(|params| { - let tys: Vec = params.iter().map(|it| it.ty(db)).collect(); + let tys: Vec> = params.iter().map(|it| it.ty(db)).collect(); let tuple_ty = Type::new_tuple(module.krate().into(), &tys); let expr = Expr::Tuple { ty: tuple_ty.clone(), params }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs index fb569f8cdae0..57ced8d8534b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs @@ -22,6 +22,7 @@ pub struct AssistConfig { pub term_search_borrowck: bool, pub code_action_grouping: bool, pub expr_fill_default: ExprFillDefaultMode, + pub prefer_self_ty: bool, } impl AssistConfig { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs index 9eb9452a2b83..207a7548f49b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs @@ -95,7 +95,7 @@ impl<'a> AssistContext<'a> { } } - pub(crate) fn db(&self) -> &RootDatabase { + pub(crate) fn db(&self) -> &'a RootDatabase { self.sema.db } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs index 6a55f39e6934..9f9d21923ff7 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -192,7 +192,7 @@ fn add_missing_impl_members_inner( fn try_gen_trait_body( ctx: &AssistContext<'_>, func: &ast::Fn, - trait_ref: hir::TraitRef, + trait_ref: hir::TraitRef<'_>, impl_def: &ast::Impl, edition: Edition, ) -> Option<()> { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 858d4369914a..1ece7ddab101 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -1,12 +1,13 @@ use std::iter::{self, Peekable}; use either::Either; -use hir::{Adt, Crate, HasAttrs, ImportPathConfig, ModuleDef, Semantics, sym}; +use hir::{Adt, AsAssocItem, Crate, HasAttrs, ImportPathConfig, ModuleDef, Semantics, sym}; use ide_db::RootDatabase; use ide_db::assists::ExprFillDefaultMode; use ide_db::syntax_helpers::suggest_name; use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast}; use itertools::Itertools; +use syntax::ToSmolStr; use syntax::ast::edit::IndentLevel; use syntax::ast::edit_in_place::Indent; use syntax::ast::syntax_factory::SyntaxFactory; @@ -79,12 +80,20 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) let make = SyntaxFactory::with_mappings(); - let module = ctx.sema.scope(expr.syntax())?.module(); + let scope = ctx.sema.scope(expr.syntax())?; + let module = scope.module(); + let self_ty = if ctx.config.prefer_self_ty { + scope + .containing_function() + .and_then(|function| function.as_assoc_item(ctx.db())?.implementing_ty(ctx.db())) + } else { + None + }; let (mut missing_pats, is_non_exhaustive, has_hidden_variants): ( Peekable>>, bool, bool, - ) = if let Some(enum_def) = resolve_enum_def(&ctx.sema, &expr) { + ) = if let Some(enum_def) = resolve_enum_def(&ctx.sema, &expr, self_ty.as_ref()) { let is_non_exhaustive = enum_def.is_non_exhaustive(ctx.db(), module.krate()); let variants = enum_def.variants(ctx.db()); @@ -102,8 +111,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) }) .filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat)); - let option_enum = FamousDefs(&ctx.sema, module.krate()).core_option_Option().map(lift_enum); - let missing_pats: Box> = if Some(enum_def) == option_enum { + let option_enum = FamousDefs(&ctx.sema, module.krate()).core_option_Option(); + let missing_pats: Box> = if matches!(enum_def, ExtendedEnum::Enum { enum_: e, .. } if Some(e) == option_enum) + { // Match `Some` variant first. cov_mark::hit!(option_order); Box::new(missing_pats.rev()) @@ -111,7 +121,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) Box::new(missing_pats) }; (missing_pats.peekable(), is_non_exhaustive, has_hidden_variants) - } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr) { + } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr, self_ty.as_ref()) { let is_non_exhaustive = enum_defs.iter().any(|enum_def| enum_def.is_non_exhaustive(ctx.db(), module.krate())); @@ -159,7 +169,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) is_non_exhaustive, has_hidden_variants, ) - } else if let Some((enum_def, len)) = resolve_array_of_enum_def(&ctx.sema, &expr) { + } else if let Some((enum_def, len)) = + resolve_array_of_enum_def(&ctx.sema, &expr, self_ty.as_ref()) + { let is_non_exhaustive = enum_def.is_non_exhaustive(ctx.db(), module.krate()); let variants = enum_def.variants(ctx.db()); @@ -373,23 +385,23 @@ fn does_pat_match_variant(pat: &Pat, var: &Pat) -> bool { } } -#[derive(Eq, PartialEq, Clone, Copy)] +#[derive(Eq, PartialEq, Clone)] enum ExtendedEnum { Bool, - Enum(hir::Enum), + Enum { enum_: hir::Enum, use_self: bool }, } #[derive(Eq, PartialEq, Clone, Copy, Debug)] enum ExtendedVariant { True, False, - Variant(hir::Variant), + Variant { variant: hir::Variant, use_self: bool }, } impl ExtendedVariant { fn should_be_hidden(self, db: &RootDatabase, krate: Crate) -> bool { match self { - ExtendedVariant::Variant(var) => { + ExtendedVariant::Variant { variant: var, .. } => { var.attrs(db).has_doc_hidden() && var.module(db).krate() != krate } _ => false, @@ -397,25 +409,35 @@ impl ExtendedVariant { } } -fn lift_enum(e: hir::Enum) -> ExtendedEnum { - ExtendedEnum::Enum(e) -} - impl ExtendedEnum { - fn is_non_exhaustive(self, db: &RootDatabase, krate: Crate) -> bool { + fn enum_( + db: &RootDatabase, + enum_: hir::Enum, + enum_ty: &hir::Type<'_>, + self_ty: Option<&hir::Type<'_>>, + ) -> Self { + ExtendedEnum::Enum { + enum_, + use_self: self_ty.is_some_and(|self_ty| self_ty.could_unify_with_deeply(db, enum_ty)), + } + } + + fn is_non_exhaustive(&self, db: &RootDatabase, krate: Crate) -> bool { match self { - ExtendedEnum::Enum(e) => { + ExtendedEnum::Enum { enum_: e, .. } => { e.attrs(db).by_key(sym::non_exhaustive).exists() && e.module(db).krate() != krate } _ => false, } } - fn variants(self, db: &RootDatabase) -> Vec { - match self { - ExtendedEnum::Enum(e) => { - e.variants(db).into_iter().map(ExtendedVariant::Variant).collect::>() - } + fn variants(&self, db: &RootDatabase) -> Vec { + match *self { + ExtendedEnum::Enum { enum_: e, use_self } => e + .variants(db) + .into_iter() + .map(|variant| ExtendedVariant::Variant { variant, use_self }) + .collect::>(), ExtendedEnum::Bool => { Vec::::from([ExtendedVariant::True, ExtendedVariant::False]) } @@ -423,9 +445,13 @@ impl ExtendedEnum { } } -fn resolve_enum_def(sema: &Semantics<'_, RootDatabase>, expr: &ast::Expr) -> Option { +fn resolve_enum_def( + sema: &Semantics<'_, RootDatabase>, + expr: &ast::Expr, + self_ty: Option<&hir::Type<'_>>, +) -> Option { sema.type_of_expr(expr)?.adjusted().autoderef(sema.db).find_map(|ty| match ty.as_adt() { - Some(Adt::Enum(e)) => Some(ExtendedEnum::Enum(e)), + Some(Adt::Enum(e)) => Some(ExtendedEnum::enum_(sema.db, e, &ty, self_ty)), _ => ty.is_bool().then_some(ExtendedEnum::Bool), }) } @@ -433,6 +459,7 @@ fn resolve_enum_def(sema: &Semantics<'_, RootDatabase>, expr: &ast::Expr) -> Opt fn resolve_tuple_of_enum_def( sema: &Semantics<'_, RootDatabase>, expr: &ast::Expr, + self_ty: Option<&hir::Type<'_>>, ) -> Option> { sema.type_of_expr(expr)? .adjusted() @@ -441,7 +468,7 @@ fn resolve_tuple_of_enum_def( .map(|ty| { ty.autoderef(sema.db).find_map(|ty| { match ty.as_adt() { - Some(Adt::Enum(e)) => Some(lift_enum(e)), + Some(Adt::Enum(e)) => Some(ExtendedEnum::enum_(sema.db, e, &ty, self_ty)), // For now we only handle expansion for a tuple of enums. Here // we map non-enum items to None and rely on `collect` to // convert Vec> into Option>. @@ -456,10 +483,11 @@ fn resolve_tuple_of_enum_def( fn resolve_array_of_enum_def( sema: &Semantics<'_, RootDatabase>, expr: &ast::Expr, + self_ty: Option<&hir::Type<'_>>, ) -> Option<(ExtendedEnum, usize)> { sema.type_of_expr(expr)?.adjusted().as_array(sema.db).and_then(|(ty, len)| { ty.autoderef(sema.db).find_map(|ty| match ty.as_adt() { - Some(Adt::Enum(e)) => Some((lift_enum(e), len)), + Some(Adt::Enum(e)) => Some((ExtendedEnum::enum_(sema.db, e, &ty, self_ty), len)), _ => ty.is_bool().then_some((ExtendedEnum::Bool, len)), }) }) @@ -474,9 +502,21 @@ fn build_pat( ) -> Option { let db = ctx.db(); match var { - ExtendedVariant::Variant(var) => { + ExtendedVariant::Variant { variant: var, use_self } => { let edition = module.krate().edition(db); - let path = mod_path_to_ast(&module.find_path(db, ModuleDef::from(var), cfg)?, edition); + let path = if use_self { + make::path_from_segments( + [ + make::path_segment(make::name_ref_self_ty()), + make::path_segment(make::name_ref( + &var.name(db).display(db, edition).to_smolstr(), + )), + ], + false, + ) + } else { + mod_path_to_ast(&module.find_path(db, ModuleDef::from(var), cfg)?, edition) + }; let fields = var.fields(db); let pat: ast::Pat = match var.kind(db) { hir::StructKind::Tuple => { @@ -509,8 +549,10 @@ fn build_pat( #[cfg(test)] mod tests { + use crate::AssistConfig; use crate::tests::{ - check_assist, check_assist_not_applicable, check_assist_target, check_assist_unresolved, + TEST_CONFIG, check_assist, check_assist_not_applicable, check_assist_target, + check_assist_unresolved, check_assist_with_config, }; use super::add_missing_match_arms; @@ -2095,4 +2137,111 @@ fn f() { "#, ); } + + #[test] + fn prefer_self() { + check_assist_with_config( + add_missing_match_arms, + AssistConfig { prefer_self_ty: true, ..TEST_CONFIG }, + r#" +enum Foo { + Bar, + Baz, +} + +impl Foo { + fn qux(&self) { + match self { + $0_ => {} + } + } +} + "#, + r#" +enum Foo { + Bar, + Baz, +} + +impl Foo { + fn qux(&self) { + match self { + Self::Bar => ${1:todo!()}, + Self::Baz => ${2:todo!()},$0 + } + } +} + "#, + ); + } + + #[test] + fn prefer_self_with_generics() { + check_assist_with_config( + add_missing_match_arms, + AssistConfig { prefer_self_ty: true, ..TEST_CONFIG }, + r#" +enum Foo { + Bar(T), + Baz, +} + +impl Foo { + fn qux(&self) { + match self { + $0_ => {} + } + } +} + "#, + r#" +enum Foo { + Bar(T), + Baz, +} + +impl Foo { + fn qux(&self) { + match self { + Self::Bar(${1:_}) => ${2:todo!()}, + Self::Baz => ${3:todo!()},$0 + } + } +} + "#, + ); + check_assist_with_config( + add_missing_match_arms, + AssistConfig { prefer_self_ty: true, ..TEST_CONFIG }, + r#" +enum Foo { + Bar(T), + Baz, +} + +impl Foo { + fn qux(v: Foo) { + match v { + $0_ => {} + } + } +} + "#, + r#" +enum Foo { + Bar(T), + Baz, +} + +impl Foo { + fn qux(v: Foo) { + match v { + Foo::Bar(${1:_}) => ${2:todo!()}, + Foo::Baz => ${3:todo!()},$0 + } + } +} + "#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs index f3243d369a0b..bb6a10d40b71 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs @@ -164,9 +164,9 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< Some(()) } -pub(super) fn find_importable_node( - ctx: &AssistContext<'_>, -) -> Option<(ImportAssets, SyntaxNode, Option)> { +pub(super) fn find_importable_node<'a: 'db, 'db>( + ctx: &'a AssistContext<'db>, +) -> Option<(ImportAssets<'db>, SyntaxNode, Option>)> { // Deduplicate this with the `expected_type_and_name` logic for completions let expected = |expr_or_pat: Either| match expr_or_pat { Either::Left(expr) => { @@ -226,7 +226,7 @@ pub(super) fn find_importable_node( } } -fn group_label(import_candidate: &ImportCandidate) -> GroupLabel { +fn group_label(import_candidate: &ImportCandidate<'_>) -> GroupLabel { let name = match import_candidate { ImportCandidate::Path(candidate) => format!("Import {}", candidate.name.text()), ImportCandidate::TraitAssocItem(candidate) => { @@ -244,7 +244,7 @@ fn group_label(import_candidate: &ImportCandidate) -> GroupLabel { pub(crate) fn relevance_score( ctx: &AssistContext<'_>, import: &LocatedImport, - expected: Option<&Type>, + expected: Option<&Type<'_>>, current_module: Option<&Module>, ) -> i32 { let mut score = 0; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs index cf45ea0a30d0..00cbef1c01c0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs @@ -309,23 +309,23 @@ fn extraction_target(node: &SyntaxNode, selection_range: TextRange) -> Option { name: ast::NameRef, self_param: Option, - params: Vec, - control_flow: ControlFlow, - ret_ty: RetType, + params: Vec>, + control_flow: ControlFlow<'db>, + ret_ty: RetType<'db>, body: FunctionBody, outliving_locals: Vec, /// Whether at least one of the container's tail expr is contained in the range we're extracting. contains_tail_expr: bool, - mods: ContainerInfo, + mods: ContainerInfo<'db>, } #[derive(Debug)] -struct Param { +struct Param<'db> { var: Local, - ty: hir::Type, + ty: hir::Type<'db>, move_local: bool, requires_mut: bool, is_copy: bool, @@ -340,10 +340,10 @@ enum ParamKind { } #[derive(Debug)] -enum FunType { +enum FunType<'db> { Unit, - Single(hir::Type), - Tuple(Vec), + Single(hir::Type<'db>), + Tuple(Vec>), } /// Where to put extracted function definition @@ -358,19 +358,19 @@ enum Anchor { // FIXME: ControlFlow and ContainerInfo both track some function modifiers, feels like these two should // probably be merged somehow. #[derive(Debug)] -struct ControlFlow { - kind: Option, +struct ControlFlow<'db> { + kind: Option>, is_async: bool, is_unsafe: bool, } /// The thing whose expression we are extracting from. Can be a function, const, static, const arg, ... #[derive(Clone, Debug)] -struct ContainerInfo { +struct ContainerInfo<'db> { is_const: bool, parent_loop: Option, /// The function's return type, const's type etc. - ret_type: Option, + ret_type: Option>, generic_param_lists: Vec, where_clauses: Vec, edition: Edition, @@ -389,11 +389,11 @@ struct ContainerInfo { /// } /// ``` #[derive(Debug, Clone)] -enum FlowKind { +enum FlowKind<'db> { /// Return with value (`return $expr;`) Return(Option), Try { - kind: TryKind, + kind: TryKind<'db>, }, /// Break with label and value (`break 'label $expr;`) Break(Option, Option), @@ -402,18 +402,18 @@ enum FlowKind { } #[derive(Debug, Clone)] -enum TryKind { +enum TryKind<'db> { Option, - Result { ty: hir::Type }, + Result { ty: hir::Type<'db> }, } #[derive(Debug)] -enum RetType { - Expr(hir::Type), +enum RetType<'db> { + Expr(hir::Type<'db>), Stmt, } -impl RetType { +impl RetType<'_> { fn is_unit(&self) -> bool { match self { RetType::Expr(ty) => ty.is_unit(), @@ -456,8 +456,8 @@ impl LocalUsages { } } -impl Function { - fn return_type(&self, ctx: &AssistContext<'_>) -> FunType { +impl<'db> Function<'db> { + fn return_type(&self, ctx: &AssistContext<'db>) -> FunType<'db> { match &self.ret_ty { RetType::Expr(ty) if ty.is_unit() => FunType::Unit, RetType::Expr(ty) => FunType::Single(ty.clone()), @@ -487,7 +487,7 @@ impl ParamKind { } } -impl Param { +impl<'db> Param<'db> { fn kind(&self) -> ParamKind { match (self.move_local, self.requires_mut, self.is_copy) { (false, true, _) => ParamKind::MutRef, @@ -497,7 +497,7 @@ impl Param { } } - fn to_arg(&self, ctx: &AssistContext<'_>, edition: Edition) -> ast::Expr { + fn to_arg(&self, ctx: &AssistContext<'db>, edition: Edition) -> ast::Expr { let var = path_expr_from_local(ctx, self.var, edition); match self.kind() { ParamKind::Value | ParamKind::MutValue => var, @@ -532,8 +532,12 @@ impl Param { } } -impl TryKind { - fn of_ty(ty: hir::Type, ctx: &AssistContext<'_>, edition: Edition) -> Option { +impl<'db> TryKind<'db> { + fn of_ty( + ty: hir::Type<'db>, + ctx: &AssistContext<'db>, + edition: Edition, + ) -> Option> { if ty.is_unknown() { // We favour Result for `expr?` return Some(TryKind::Result { ty }); @@ -551,7 +555,7 @@ impl TryKind { } } -impl FlowKind { +impl<'db> FlowKind<'db> { fn make_result_handler(&self, expr: Option) -> ast::Expr { match self { FlowKind::Return(_) => make::expr_return(expr), @@ -567,7 +571,7 @@ impl FlowKind { } } - fn expr_ty(&self, ctx: &AssistContext<'_>) -> Option { + fn expr_ty(&self, ctx: &AssistContext<'db>) -> Option> { match self { FlowKind::Return(Some(expr)) | FlowKind::Break(_, Some(expr)) => { ctx.sema.type_of_expr(expr).map(TypeInfo::adjusted) @@ -876,11 +880,11 @@ impl FunctionBody { (res, self_param) } - fn analyze_container( + fn analyze_container<'db>( &self, - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, edition: Edition, - ) -> Option<(ContainerInfo, bool)> { + ) -> Option<(ContainerInfo<'db>, bool)> { let mut ancestors = self.parent()?.ancestors(); let infer_expr_opt = |expr| sema.type_of_expr(&expr?).map(TypeInfo::adjusted); let mut parent_loop = None; @@ -985,7 +989,7 @@ impl FunctionBody { )) } - fn return_ty(&self, ctx: &AssistContext<'_>) -> Option { + fn return_ty<'db>(&self, ctx: &AssistContext<'db>) -> Option> { match self.tail_expr() { Some(expr) => ctx.sema.type_of_expr(&expr).map(TypeInfo::original).map(RetType::Expr), None => Some(RetType::Stmt), @@ -1006,11 +1010,11 @@ impl FunctionBody { } /// Analyses the function body for external control flow. - fn external_control_flow( + fn external_control_flow<'db>( &self, - ctx: &AssistContext<'_>, - container_info: &ContainerInfo, - ) -> Option { + ctx: &AssistContext<'db>, + container_info: &ContainerInfo<'db>, + ) -> Option> { let mut ret_expr = None; let mut try_expr = None; let mut break_expr = None; @@ -1096,12 +1100,12 @@ impl FunctionBody { /// find variables that should be extracted as params /// /// Computes additional info that affects param type and mutability - fn extracted_function_params( + fn extracted_function_params<'db>( &self, - ctx: &AssistContext<'_>, - container_info: &ContainerInfo, + ctx: &AssistContext<'db>, + container_info: &ContainerInfo<'db>, locals: FxIndexSet, - ) -> Vec { + ) -> Vec> { locals .into_iter() .sorted() @@ -1449,7 +1453,7 @@ fn fixup_call_site(builder: &mut SourceChangeBuilder, body: &FunctionBody) { } } -fn make_call(ctx: &AssistContext<'_>, fun: &Function, indent: IndentLevel) -> SyntaxNode { +fn make_call(ctx: &AssistContext<'_>, fun: &Function<'_>, indent: IndentLevel) -> SyntaxNode { let ret_ty = fun.return_type(ctx); let args = make::arg_list(fun.params.iter().map(|param| param.to_arg(ctx, fun.mods.edition))); @@ -1508,17 +1512,17 @@ fn make_call(ctx: &AssistContext<'_>, fun: &Function, indent: IndentLevel) -> Sy } } -enum FlowHandler { +enum FlowHandler<'db> { None, - Try { kind: TryKind }, - If { action: FlowKind }, - IfOption { action: FlowKind }, - MatchOption { none: FlowKind }, - MatchResult { err: FlowKind }, + Try { kind: TryKind<'db> }, + If { action: FlowKind<'db> }, + IfOption { action: FlowKind<'db> }, + MatchOption { none: FlowKind<'db> }, + MatchResult { err: FlowKind<'db> }, } -impl FlowHandler { - fn from_ret_ty(fun: &Function, ret_ty: &FunType) -> FlowHandler { +impl<'db> FlowHandler<'db> { + fn from_ret_ty(fun: &Function<'db>, ret_ty: &FunType<'db>) -> FlowHandler<'db> { if fun.contains_tail_expr { return FlowHandler::None; } @@ -1628,7 +1632,7 @@ fn path_expr_from_local(ctx: &AssistContext<'_>, var: Local, edition: Edition) - fn format_function( ctx: &AssistContext<'_>, module: hir::Module, - fun: &Function, + fun: &Function<'_>, old_indent: IndentLevel, ) -> ast::Fn { let fun_name = make::name(&fun.name.text()); @@ -1654,7 +1658,7 @@ fn format_function( fn make_generic_params_and_where_clause( ctx: &AssistContext<'_>, - fun: &Function, + fun: &Function<'_>, ) -> (Option, Option) { let used_type_params = fun.type_params(ctx); @@ -1666,7 +1670,7 @@ fn make_generic_params_and_where_clause( fn make_generic_param_list( ctx: &AssistContext<'_>, - fun: &Function, + fun: &Function<'_>, used_type_params: &[TypeParam], ) -> Option { let mut generic_params = fun @@ -1703,7 +1707,7 @@ fn param_is_required( fn make_where_clause( ctx: &AssistContext<'_>, - fun: &Function, + fun: &Function<'_>, used_type_params: &[TypeParam], ) -> Option { let mut predicates = fun @@ -1743,9 +1747,9 @@ fn resolved_type_param(ctx: &AssistContext<'_>, pred: &ast::WherePred) -> Option } } -impl Function { +impl<'db> Function<'db> { /// Collect all the `TypeParam`s used in the `body` and `params`. - fn type_params(&self, ctx: &AssistContext<'_>) -> Vec { + fn type_params(&self, ctx: &AssistContext<'db>) -> Vec { let type_params_in_descendant_paths = self.body.descendant_paths().filter_map(|it| match ctx.sema.resolve_path(&it) { Some(PathResolution::TypeParam(type_param)) => Some(type_param), @@ -1808,8 +1812,8 @@ impl Function { } } -impl FunType { - fn make_ty(&self, ctx: &AssistContext<'_>, module: hir::Module) -> ast::Type { +impl<'db> FunType<'db> { + fn make_ty(&self, ctx: &AssistContext<'db>, module: hir::Module) -> ast::Type { match self { FunType::Unit => make::ty_unit(), FunType::Single(ty) => make_ty(ty, ctx, module), @@ -1831,7 +1835,11 @@ impl FunType { } } -fn make_body(ctx: &AssistContext<'_>, old_indent: IndentLevel, fun: &Function) -> ast::BlockExpr { +fn make_body( + ctx: &AssistContext<'_>, + old_indent: IndentLevel, + fun: &Function<'_>, +) -> ast::BlockExpr { let ret_ty = fun.return_type(ctx); let handler = FlowHandler::from_ret_ty(fun, &ret_ty); @@ -2009,19 +2017,19 @@ fn with_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr make::hacky_block_expr(elements, Some(tail_expr)) } -fn format_type(ty: &hir::Type, ctx: &AssistContext<'_>, module: hir::Module) -> String { +fn format_type(ty: &hir::Type<'_>, ctx: &AssistContext<'_>, module: hir::Module) -> String { ty.display_source_code(ctx.db(), module.into(), true).ok().unwrap_or_else(|| "_".to_owned()) } -fn make_ty(ty: &hir::Type, ctx: &AssistContext<'_>, module: hir::Module) -> ast::Type { +fn make_ty(ty: &hir::Type<'_>, ctx: &AssistContext<'_>, module: hir::Module) -> ast::Type { let ty_str = format_type(ty, ctx, module); make::ty(&ty_str) } fn rewrite_body_segment( ctx: &AssistContext<'_>, - params: &[Param], - handler: &FlowHandler, + params: &[Param<'_>], + handler: &FlowHandler<'_>, syntax: &SyntaxNode, ) -> SyntaxNode { let syntax = fix_param_usages(ctx, params, syntax); @@ -2030,8 +2038,12 @@ fn rewrite_body_segment( } /// change all usages to account for added `&`/`&mut` for some params -fn fix_param_usages(ctx: &AssistContext<'_>, params: &[Param], syntax: &SyntaxNode) -> SyntaxNode { - let mut usages_for_param: Vec<(&Param, Vec)> = Vec::new(); +fn fix_param_usages( + ctx: &AssistContext<'_>, + params: &[Param<'_>], + syntax: &SyntaxNode, +) -> SyntaxNode { + let mut usages_for_param: Vec<(&Param<'_>, Vec)> = Vec::new(); let tm = TreeMutator::new(syntax); @@ -2085,7 +2097,7 @@ fn fix_param_usages(ctx: &AssistContext<'_>, params: &[Param], syntax: &SyntaxNo res } -fn update_external_control_flow(handler: &FlowHandler, syntax: &SyntaxNode) { +fn update_external_control_flow(handler: &FlowHandler<'_>, syntax: &SyntaxNode) { let mut nested_loop = None; let mut nested_scope = None; for event in syntax.preorder() { @@ -2146,7 +2158,10 @@ fn update_external_control_flow(handler: &FlowHandler, syntax: &SyntaxNode) { } } -fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option) -> Option { +fn make_rewritten_flow( + handler: &FlowHandler<'_>, + arg_expr: Option, +) -> Option { let value = match handler { FlowHandler::None | FlowHandler::Try { .. } => return None, FlowHandler::If { .. } => make::expr_call( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs index 30084d23d1fb..78ae815dc87a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs @@ -307,7 +307,7 @@ impl FunctionBuilder { ctx: &AssistContext<'_>, call: &ast::MethodCallExpr, name: &ast::NameRef, - receiver_ty: Type, + receiver_ty: Type<'_>, target_module: Module, target: GeneratedFunctionTarget, ) -> Option { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs index 6f028e58d0cd..b7b8bc604a51 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs @@ -283,11 +283,11 @@ impl CallInfo { } } -fn get_fn_params( - db: &dyn HirDatabase, +fn get_fn_params<'db>( + db: &'db dyn HirDatabase, function: hir::Function, param_list: &ast::ParamList, -) -> Option, hir::Param)>> { +) -> Option, hir::Param<'db>)>> { let mut assoc_fn_params = function.assoc_fn_params(db).into_iter(); let mut params = Vec::new(); @@ -316,7 +316,7 @@ fn inline( function_def_file_id: EditionedFileId, function: hir::Function, fn_body: &ast::BlockExpr, - params: &[(ast::Pat, Option, hir::Param)], + params: &[(ast::Pat, Option, hir::Param<'_>)], CallInfo { node, arguments, generic_arg_list, krate }: &CallInfo, ) -> ast::Expr { let file_id = sema.hir_file_for(fn_body.syntax()); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs index e5ed04fdc7c9..b11d3792bc4c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs @@ -58,7 +58,7 @@ pub(crate) fn inline_const_as_literal(acc: &mut Assists, ctx: &AssistContext<'_> fn validate_type_recursively( ctx: &AssistContext<'_>, - ty_hir: Option<&hir::Type>, + ty_hir: Option<&hir::Type<'_>>, refed: bool, fuel: i32, ) -> Option<()> { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs index 42f35210b496..08170f81b283 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs @@ -105,7 +105,7 @@ fn contains_placeholder(a: &ast::MatchArm) -> bool { } fn are_same_types( - current_arm_types: &FxHashMap>, + current_arm_types: &FxHashMap>>, arm: &ast::MatchArm, ctx: &AssistContext<'_>, ) -> bool { @@ -121,15 +121,15 @@ fn are_same_types( true } -fn get_arm_types( - context: &AssistContext<'_>, +fn get_arm_types<'db>( + context: &AssistContext<'db>, arm: &ast::MatchArm, -) -> FxHashMap> { - let mut mapping: FxHashMap> = FxHashMap::default(); +) -> FxHashMap>> { + let mut mapping: FxHashMap>> = FxHashMap::default(); - fn recurse( - map: &mut FxHashMap>, - ctx: &AssistContext<'_>, + fn recurse<'db>( + map: &mut FxHashMap>>, + ctx: &AssistContext<'db>, pat: &Option, ) { if let Some(local_pat) = pat { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs index 07d2f52a34ee..8834ad97652e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs @@ -217,7 +217,7 @@ fn item_as_trait(db: &RootDatabase, item: hir::ItemInNs) -> Option { } } -fn group_label(candidate: &ImportCandidate) -> GroupLabel { +fn group_label(candidate: &ImportCandidate<'_>) -> GroupLabel { let name = match candidate { ImportCandidate::Path(it) => &it.name, ImportCandidate::TraitAssocItem(it) | ImportCandidate::TraitMethod(it) => { @@ -230,7 +230,7 @@ fn group_label(candidate: &ImportCandidate) -> GroupLabel { fn label( db: &RootDatabase, - candidate: &ImportCandidate, + candidate: &ImportCandidate<'_>, import: &LocatedImport, edition: Edition, ) -> String { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs index 16debc4d7285..c38bdfdccf5b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs @@ -117,7 +117,7 @@ pub(crate) fn remove_unused_imports(acc: &mut Assists, ctx: &AssistContext<'_>) if unused.peek().is_some() { acc.add( AssistId::quick_fix("remove_unused_imports"), - "Remove all the unused imports", + "Remove all unused imports", selected_el.text_range(), |builder| { let unused: Vec = unused.map(|x| builder.make_mut(x)).collect(); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs index 6af8e1482c24..019ddaf1441d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs @@ -46,7 +46,7 @@ pub(crate) fn term_search(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< return None; } - let mut formatter = |_: &hir::Type| String::from("todo!()"); + let mut formatter = |_: &hir::Type<'_>| String::from("todo!()"); let edition = scope.krate().edition(ctx.db()); let paths = paths @@ -100,7 +100,9 @@ fn f() { let a: u128 = 1; let b: u128 = todo$0!() }"#, fn test_complete_todo_with_msg() { check_assist( term_search, - r#"//- minicore: todo, unimplemented + // FIXME: Since we are lacking of `super let`, term search fails due to borrowck failure. + // Should implement super let and remove `fmt_before_1_89_0` + r#"//- minicore: todo, unimplemented, fmt_before_1_89_0 fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#, r#"fn f() { let a: u128 = 1; let b: u128 = a }"#, ) @@ -110,7 +112,9 @@ fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#, fn test_complete_unimplemented_with_msg() { check_assist( term_search, - r#"//- minicore: todo, unimplemented + // FIXME: Since we are lacking of `super let`, term search fails due to borrowck failure. + // Should implement super let and remove `fmt_before_1_89_0` + r#"//- minicore: todo, unimplemented, fmt_before_1_89_0 fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#, r#"fn f() { let a: u128 = 1; let b: u128 = a }"#, ) @@ -120,7 +124,9 @@ fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#, fn test_complete_unimplemented() { check_assist( term_search, - r#"//- minicore: todo, unimplemented + // FIXME: Since we are lacking of `super let`, term search fails due to borrowck failure. + // Should implement super let and remove `fmt_before_1_89_0` + r#"//- minicore: todo, unimplemented, fmt_before_1_89_0 fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#, r#"fn f() { let a: u128 = 1; let b: u128 = a }"#, ) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs index 5e6889792db6..cda2ad43278a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs @@ -37,6 +37,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig { term_search_borrowck: true, code_action_grouping: true, expr_fill_default: ExprFillDefaultMode::Todo, + prefer_self_ty: false, }; pub(crate) const TEST_CONFIG_NO_GROUPING: AssistConfig = AssistConfig { @@ -57,6 +58,7 @@ pub(crate) const TEST_CONFIG_NO_GROUPING: AssistConfig = AssistConfig { term_search_borrowck: true, code_action_grouping: false, expr_fill_default: ExprFillDefaultMode::Todo, + prefer_self_ty: false, }; pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig { @@ -77,6 +79,7 @@ pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig { term_search_borrowck: true, code_action_grouping: true, expr_fill_default: ExprFillDefaultMode::Todo, + prefer_self_ty: false, }; pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig { @@ -97,6 +100,7 @@ pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig { term_search_borrowck: true, code_action_grouping: true, expr_fill_default: ExprFillDefaultMode::Todo, + prefer_self_ty: false, }; pub(crate) fn with_single_file(text: &str) -> (RootDatabase, EditionedFileId) { @@ -113,6 +117,23 @@ pub(crate) fn check_assist( check(assist, ra_fixture_before, ExpectedResult::After(&ra_fixture_after), None); } +#[track_caller] +pub(crate) fn check_assist_with_config( + assist: Handler, + config: AssistConfig, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, +) { + let ra_fixture_after = trim_indent(ra_fixture_after); + check_with_config( + config, + assist, + ra_fixture_before, + ExpectedResult::After(&ra_fixture_after), + None, + ); +} + #[track_caller] pub(crate) fn check_assist_no_snippet_cap( assist: Handler, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index ef6914fda1d5..1a91053f93ca 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -405,7 +405,7 @@ pub(crate) fn does_pat_variant_nested_or_literal(ctx: &AssistContext<'_>, pat: & } fn check_pat_variant_from_enum(ctx: &AssistContext<'_>, pat: &ast::Pat) -> bool { - ctx.sema.type_of_pat(pat).is_none_or(|ty: hir::TypeInfo| { + ctx.sema.type_of_pat(pat).is_none_or(|ty: hir::TypeInfo<'_>| { ty.adjusted().as_adt().is_some_and(|adt| matches!(adt, hir::Adt::Enum(_))) }) } @@ -780,9 +780,9 @@ pub(crate) fn add_method_to_adt( } #[derive(Debug)] -pub(crate) struct ReferenceConversion { +pub(crate) struct ReferenceConversion<'db> { conversion: ReferenceConversionType, - ty: hir::Type, + ty: hir::Type<'db>, impls_deref: bool, } @@ -802,10 +802,10 @@ enum ReferenceConversionType { Result, } -impl ReferenceConversion { +impl<'db> ReferenceConversion<'db> { pub(crate) fn convert_type( &self, - db: &dyn HirDatabase, + db: &'db dyn HirDatabase, display_target: DisplayTarget, ) -> ast::Type { let ty = match self.conversion { @@ -878,11 +878,11 @@ impl ReferenceConversion { // FIXME: It should return a new hir::Type, but currently constructing new types is too cumbersome // and all users of this function operate on string type names, so they can do the conversion // itself themselves. -pub(crate) fn convert_reference_type( - ty: hir::Type, - db: &RootDatabase, - famous_defs: &FamousDefs<'_, '_>, -) -> Option { +pub(crate) fn convert_reference_type<'db>( + ty: hir::Type<'db>, + db: &'db RootDatabase, + famous_defs: &FamousDefs<'_, 'db>, +) -> Option> { handle_copy(&ty, db) .or_else(|| handle_as_ref_str(&ty, db, famous_defs)) .or_else(|| handle_as_ref_slice(&ty, db, famous_defs)) @@ -892,18 +892,21 @@ pub(crate) fn convert_reference_type( .map(|(conversion, impls_deref)| ReferenceConversion { ty, conversion, impls_deref }) } -fn could_deref_to_target(ty: &hir::Type, target: &hir::Type, db: &dyn HirDatabase) -> bool { +fn could_deref_to_target(ty: &hir::Type<'_>, target: &hir::Type<'_>, db: &dyn HirDatabase) -> bool { let ty_ref = ty.add_reference(hir::Mutability::Shared); let target_ref = target.add_reference(hir::Mutability::Shared); ty_ref.could_coerce_to(db, &target_ref) } -fn handle_copy(ty: &hir::Type, db: &dyn HirDatabase) -> Option<(ReferenceConversionType, bool)> { +fn handle_copy( + ty: &hir::Type<'_>, + db: &dyn HirDatabase, +) -> Option<(ReferenceConversionType, bool)> { ty.is_copy(db).then_some((ReferenceConversionType::Copy, true)) } fn handle_as_ref_str( - ty: &hir::Type, + ty: &hir::Type<'_>, db: &dyn HirDatabase, famous_defs: &FamousDefs<'_, '_>, ) -> Option<(ReferenceConversionType, bool)> { @@ -914,7 +917,7 @@ fn handle_as_ref_str( } fn handle_as_ref_slice( - ty: &hir::Type, + ty: &hir::Type<'_>, db: &dyn HirDatabase, famous_defs: &FamousDefs<'_, '_>, ) -> Option<(ReferenceConversionType, bool)> { @@ -928,7 +931,7 @@ fn handle_as_ref_slice( } fn handle_dereferenced( - ty: &hir::Type, + ty: &hir::Type<'_>, db: &dyn HirDatabase, famous_defs: &FamousDefs<'_, '_>, ) -> Option<(ReferenceConversionType, bool)> { @@ -941,7 +944,7 @@ fn handle_dereferenced( } fn handle_option_as_ref( - ty: &hir::Type, + ty: &hir::Type<'_>, db: &dyn HirDatabase, famous_defs: &FamousDefs<'_, '_>, ) -> Option<(ReferenceConversionType, bool)> { @@ -953,7 +956,7 @@ fn handle_option_as_ref( } fn handle_result_as_ref( - ty: &hir::Type, + ty: &hir::Type<'_>, db: &dyn HirDatabase, famous_defs: &FamousDefs<'_, '_>, ) -> Option<(ReferenceConversionType, bool)> { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs index 4ea56dc46aaa..c58bdd9e8ede 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs @@ -17,7 +17,7 @@ pub(crate) fn gen_trait_fn_body( func: &ast::Fn, trait_path: &ast::Path, adt: &ast::Adt, - trait_ref: Option, + trait_ref: Option>, ) -> Option<()> { match trait_path.segment()?.name_ref()?.text().as_str() { "Clone" => gen_clone_impl(adt, func), @@ -405,7 +405,7 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { } /// Generate a `PartialEq` impl based on the fields and members of the target type. -fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option) -> Option<()> { +fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option>) -> Option<()> { stdx::always!(func.name().is_some_and(|name| name.text() == "eq")); fn gen_eq_chain(expr: Option, cmp: ast::Expr) -> Option { match expr { @@ -599,7 +599,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option) - Some(()) } -fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option) -> Option<()> { +fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option>) -> Option<()> { stdx::always!(func.name().is_some_and(|name| name.text() == "partial_cmp")); fn gen_partial_eq_match(match_target: ast::Expr) -> Option { let mut arms = vec![]; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs index 5d68aca9e615..65072d936f63 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs @@ -161,7 +161,11 @@ impl Completions { item.add_to(self, ctx.db); } - pub(crate) fn add_expr(&mut self, ctx: &CompletionContext<'_>, expr: &hir::term_search::Expr) { + pub(crate) fn add_expr( + &mut self, + ctx: &CompletionContext<'_>, + expr: &hir::term_search::Expr<'_>, + ) { if let Some(item) = render_expr(ctx, expr) { item.add_to(self, ctx.db) } @@ -170,7 +174,7 @@ impl Completions { pub(crate) fn add_crate_roots( &mut self, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, ) { ctx.process_all_names(&mut |name, res, doc_aliases| match res { ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) if m.is_crate_root() => { @@ -183,7 +187,7 @@ impl Completions { pub(crate) fn add_path_resolution( &mut self, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, local_name: hir::Name, resolution: hir::ScopeDef, doc_aliases: Vec, @@ -232,7 +236,7 @@ impl Completions { pub(crate) fn add_enum_variants( &mut self, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, e: hir::Enum, ) { if !ctx.check_stability_and_hidden(e) { @@ -246,7 +250,7 @@ impl Completions { pub(crate) fn add_module( &mut self, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, module: hir::Module, local_name: hir::Name, doc_aliases: Vec, @@ -263,7 +267,7 @@ impl Completions { pub(crate) fn add_macro( &mut self, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, mac: hir::Macro, local_name: hir::Name, ) { @@ -286,7 +290,7 @@ impl Completions { pub(crate) fn add_function( &mut self, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, func: hir::Function, local_name: Option, ) { @@ -312,7 +316,7 @@ impl Completions { pub(crate) fn add_method( &mut self, ctx: &CompletionContext<'_>, - dot_access: &DotAccess, + dot_access: &DotAccess<'_>, func: hir::Function, receiver: Option, local_name: Option, @@ -340,7 +344,7 @@ impl Completions { pub(crate) fn add_method_with_import( &mut self, ctx: &CompletionContext<'_>, - dot_access: &DotAccess, + dot_access: &DotAccess<'_>, func: hir::Function, import: LocatedImport, ) { @@ -407,7 +411,7 @@ impl Completions { pub(crate) fn add_qualified_enum_variant( &mut self, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, variant: hir::Variant, path: hir::ModPath, ) { @@ -424,7 +428,7 @@ impl Completions { pub(crate) fn add_enum_variant( &mut self, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, variant: hir::Variant, local_name: Option, ) { @@ -447,10 +451,10 @@ impl Completions { pub(crate) fn add_field( &mut self, ctx: &CompletionContext<'_>, - dot_access: &DotAccess, + dot_access: &DotAccess<'_>, receiver: Option, field: hir::Field, - ty: &hir::Type, + ty: &hir::Type<'_>, ) { let is_private_editable = match ctx.is_visible(&field) { Visible::Yes => false, @@ -471,7 +475,7 @@ impl Completions { pub(crate) fn add_struct_literal( &mut self, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, strukt: hir::Struct, path: Option, local_name: Option, @@ -518,7 +522,7 @@ impl Completions { ctx: &CompletionContext<'_>, receiver: Option, field: usize, - ty: &hir::Type, + ty: &hir::Type<'_>, ) { // Only used for (unnamed) tuples, whose all fields *are* stable. No need to check // stability here. @@ -550,7 +554,7 @@ impl Completions { &mut self, ctx: &CompletionContext<'_>, pattern_ctx: &PatternContext, - path_ctx: Option<&PathCompletionCtx>, + path_ctx: Option<&PathCompletionCtx<'_>>, variant: hir::Variant, local_name: Option, ) { @@ -704,7 +708,7 @@ pub(super) fn complete_name( pub(super) fn complete_name_ref( acc: &mut Completions, ctx: &CompletionContext<'_>, - NameRefContext { nameref, kind }: &NameRefContext, + NameRefContext { nameref, kind }: &NameRefContext<'_>, ) { match kind { NameRefKind::Path(path_ctx) => { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs index 705402c785a2..c542e140df54 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs @@ -86,7 +86,7 @@ pub(crate) fn complete_known_attribute_input( pub(crate) fn complete_attribute_path( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, + path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx<'_>, &AttrCtx { kind, annotated_item_kind, ref derive_helpers }: &AttrCtx, ) { let is_inner = kind == AttrKind::Inner; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/derive.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/derive.rs index 2fc07e013828..267d92b6c090 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/derive.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/derive.rs @@ -13,7 +13,7 @@ use crate::{ pub(crate) fn complete_derive_path( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, + path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx<'_>, existing_derives: &ExistingDerives, ) { let core = ctx.famous_defs().core(); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs index 4f21136d214e..5340d65a142d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs @@ -18,7 +18,7 @@ use crate::{ pub(crate) fn complete_dot( acc: &mut Completions, ctx: &CompletionContext<'_>, - dot_access: &DotAccess, + dot_access: &DotAccess<'_>, ) { let receiver_ty = match dot_access { DotAccess { receiver_ty: Some(receiver_ty), .. } => &receiver_ty.original, @@ -130,8 +130,8 @@ pub(crate) fn complete_dot( pub(crate) fn complete_undotted_self( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, - expr_ctx: &PathExprCtx, + path_ctx: &PathCompletionCtx<'_>, + expr_ctx: &PathExprCtx<'_>, ) { if !ctx.config.enable_self_on_the_fly { return; @@ -198,9 +198,9 @@ pub(crate) fn complete_undotted_self( fn complete_fields( acc: &mut Completions, ctx: &CompletionContext<'_>, - receiver: &hir::Type, - mut named_field: impl FnMut(&mut Completions, hir::Field, hir::Type), - mut tuple_index: impl FnMut(&mut Completions, usize, hir::Type), + receiver: &hir::Type<'_>, + mut named_field: impl FnMut(&mut Completions, hir::Field, hir::Type<'_>), + mut tuple_index: impl FnMut(&mut Completions, usize, hir::Type<'_>), is_field_access: bool, is_method_access_with_parens: bool, ) { @@ -230,7 +230,7 @@ fn complete_fields( fn complete_methods( ctx: &CompletionContext<'_>, - receiver: &hir::Type, + receiver: &hir::Type<'_>, traits_in_scope: &FxHashSet, f: impl FnMut(hir::Function), ) { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index 7fbd1fbc1af4..2133291b1de1 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -47,8 +47,8 @@ where pub(crate) fn complete_expr_path( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, - expr_ctx: &PathExprCtx, + path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx<'_>, + expr_ctx: &PathExprCtx<'_>, ) { let _p = tracing::info_span!("complete_expr_path").entered(); if !ctx.qualifier_ctx.none() { @@ -145,10 +145,16 @@ pub(crate) fn complete_expr_path( }); match resolution { hir::PathResolution::Def(hir::ModuleDef::Module(module)) => { - // Set visible_from to None so private items are returned. - // They will be possibly filtered out in add_path_resolution() - // via def_is_visible(). - let module_scope = module.scope(ctx.db, None); + let visible_from = if ctx.config.enable_private_editable { + // Set visible_from to None so private items are returned. + // They will be possibly filtered out in add_path_resolution() + // via def_is_visible(). + None + } else { + Some(ctx.module) + }; + + let module_scope = module.scope(ctx.db, visible_from); for (name, def) in module_scope { if scope_def_applicable(def) { acc.add_path_resolution( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/field.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/field.rs index 1441b0e3a01a..26afa9c8ad96 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/field.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/field.rs @@ -8,7 +8,7 @@ use crate::{ pub(crate) fn complete_field_list_tuple_variant( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, ) { if ctx.qualifier_ctx.vis_node.is_some() { } else if let PathCompletionCtx { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs index a74756138090..dad8a76de87d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs @@ -111,7 +111,7 @@ use crate::{ pub(crate) fn import_on_the_fly_path( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, ) -> Option<()> { if !ctx.config.enable_imports_on_the_fly { return None; @@ -175,7 +175,7 @@ pub(crate) fn import_on_the_fly_pat( pub(crate) fn import_on_the_fly_dot( acc: &mut Completions, ctx: &CompletionContext<'_>, - dot_access: &DotAccess, + dot_access: &DotAccess<'_>, ) -> Option<()> { if !ctx.config.enable_imports_on_the_fly { return None; @@ -203,8 +203,8 @@ pub(crate) fn import_on_the_fly_dot( fn import_on_the_fly( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx @ PathCompletionCtx { kind, .. }: &PathCompletionCtx, - import_assets: ImportAssets, + path_ctx @ PathCompletionCtx { kind, .. }: &PathCompletionCtx<'_>, + import_assets: ImportAssets<'_>, position: SyntaxNode, potential_import_name: String, ) -> Option<()> { @@ -290,7 +290,7 @@ fn import_on_the_fly_pat_( acc: &mut Completions, ctx: &CompletionContext<'_>, pattern_ctx: &PatternContext, - import_assets: ImportAssets, + import_assets: ImportAssets<'_>, position: SyntaxNode, potential_import_name: String, ) -> Option<()> { @@ -335,8 +335,8 @@ fn import_on_the_fly_pat_( fn import_on_the_fly_method( acc: &mut Completions, ctx: &CompletionContext<'_>, - dot_access: &DotAccess, - import_assets: ImportAssets, + dot_access: &DotAccess<'_>, + import_assets: ImportAssets<'_>, position: SyntaxNode, potential_import_name: String, ) -> Option<()> { @@ -400,11 +400,11 @@ fn import_name(ctx: &CompletionContext<'_>) -> String { if token_kind.is_any_identifier() { ctx.token.to_string() } else { String::new() } } -fn import_assets_for_path( - ctx: &CompletionContext<'_>, +fn import_assets_for_path<'db>( + ctx: &CompletionContext<'db>, potential_import_name: &str, qualifier: Option, -) -> Option { +) -> Option> { let _p = tracing::info_span!("import_assets_for_path", ?potential_import_name, ?qualifier).entered(); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs index 893997cee473..6c001bd16bfe 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs @@ -10,8 +10,8 @@ pub(crate) mod trait_impl; pub(crate) fn complete_item_list_in_expr( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, - expr_ctx: &PathExprCtx, + path_ctx: &PathCompletionCtx<'_>, + expr_ctx: &PathExprCtx<'_>, ) { if !expr_ctx.in_block_expr { return; @@ -25,7 +25,7 @@ pub(crate) fn complete_item_list_in_expr( pub(crate) fn complete_item_list( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, + path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx<'_>, kind: &ItemListKind, ) { let _p = tracing::info_span!("complete_item_list").entered(); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs index 58aead73fd6f..092219a058a1 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs @@ -122,7 +122,7 @@ fn complete_trait_impl_name( pub(crate) fn complete_trait_impl_item_by_name( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, name_ref: &Option, impl_: &Option, ) { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs index ea3511d31caf..62fae1cb2374 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs @@ -124,7 +124,7 @@ pub(crate) fn complete_pattern( pub(crate) fn complete_pattern_path( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, + path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx<'_>, ) { match qualified { Qualified::With { resolution: Some(resolution), super_chain_len, .. } => { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs index 3cdf2112835d..d0023852acf9 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs @@ -11,6 +11,7 @@ use ide_db::{ text_edit::TextEdit, ty_filter::TryEnum, }; +use itertools::Either; use stdx::never; use syntax::{ SyntaxKind::{BLOCK_EXPR, EXPR_STMT, FOR_EXPR, IF_EXPR, LOOP_EXPR, STMT_LIST, WHILE_EXPR}, @@ -28,7 +29,7 @@ use crate::{ pub(crate) fn complete_postfix( acc: &mut Completions, ctx: &CompletionContext<'_>, - dot_access: &DotAccess, + dot_access: &DotAccess<'_>, ) { if !ctx.config.enable_postfix_completions { return; @@ -86,98 +87,10 @@ pub(crate) fn complete_postfix( } } - let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty.strip_references()); - if let Some(try_enum) = &try_enum { - match try_enum { - TryEnum::Result => { - postfix_snippet( - "ifl", - "if let Ok {}", - &format!("if let Ok($1) = {receiver_text} {{\n $0\n}}"), - ) - .add_to(acc, ctx.db); - - postfix_snippet( - "lete", - "let Ok else {}", - &format!("let Ok($1) = {receiver_text} else {{\n $2\n}};\n$0"), - ) - .add_to(acc, ctx.db); - - postfix_snippet( - "while", - "while let Ok {}", - &format!("while let Ok($1) = {receiver_text} {{\n $0\n}}"), - ) - .add_to(acc, ctx.db); - } - TryEnum::Option => { - postfix_snippet( - "ifl", - "if let Some {}", - &format!("if let Some($1) = {receiver_text} {{\n $0\n}}"), - ) - .add_to(acc, ctx.db); - - postfix_snippet( - "lete", - "let Some else {}", - &format!("let Some($1) = {receiver_text} else {{\n $2\n}};\n$0"), - ) - .add_to(acc, ctx.db); - - postfix_snippet( - "while", - "while let Some {}", - &format!("while let Some($1) = {receiver_text} {{\n $0\n}}"), - ) - .add_to(acc, ctx.db); - } - } - } else if receiver_ty.is_bool() || receiver_ty.is_unknown() { - postfix_snippet("if", "if expr {}", &format!("if {receiver_text} {{\n $0\n}}")) - .add_to(acc, ctx.db); - postfix_snippet("while", "while expr {}", &format!("while {receiver_text} {{\n $0\n}}")) - .add_to(acc, ctx.db); - postfix_snippet("not", "!expr", &format!("!{receiver_text}")).add_to(acc, ctx.db); - } else if let Some(trait_) = ctx.famous_defs().core_iter_IntoIterator() { - if receiver_ty.impls_trait(ctx.db, trait_, &[]) { - postfix_snippet( - "for", - "for ele in expr {}", - &format!("for ele in {receiver_text} {{\n $0\n}}"), - ) - .add_to(acc, ctx.db); - } - } - postfix_snippet("ref", "&expr", &format!("&{receiver_text}")).add_to(acc, ctx.db); postfix_snippet("refm", "&mut expr", &format!("&mut {receiver_text}")).add_to(acc, ctx.db); postfix_snippet("deref", "*expr", &format!("*{receiver_text}")).add_to(acc, ctx.db); - let mut block_should_be_wrapped = true; - if dot_receiver.syntax().kind() == BLOCK_EXPR { - block_should_be_wrapped = false; - if let Some(parent) = dot_receiver.syntax().parent() { - if matches!(parent.kind(), IF_EXPR | WHILE_EXPR | LOOP_EXPR | FOR_EXPR) { - block_should_be_wrapped = true; - } - } - }; - let unsafe_completion_string = if block_should_be_wrapped { - format!("unsafe {{ {receiver_text} }}") - } else { - format!("unsafe {receiver_text}") - }; - postfix_snippet("unsafe", "unsafe {}", &unsafe_completion_string).add_to(acc, ctx.db); - - let const_completion_string = if block_should_be_wrapped { - format!("const {{ {receiver_text} }}") - } else { - format!("const {receiver_text}") - }; - postfix_snippet("const", "const {}", &const_completion_string).add_to(acc, ctx.db); - // The rest of the postfix completions create an expression that moves an argument, // so it's better to consider references now to avoid breaking the compilation @@ -195,37 +108,6 @@ pub(crate) fn complete_postfix( add_custom_postfix_completions(acc, ctx, &postfix_snippet, &receiver_text); } - match try_enum { - Some(try_enum) => match try_enum { - TryEnum::Result => { - postfix_snippet( - "match", - "match expr {}", - &format!("match {receiver_text} {{\n Ok(${{1:_}}) => {{$2}},\n Err(${{3:_}}) => {{$0}},\n}}"), - ) - .add_to(acc, ctx.db); - } - TryEnum::Option => { - postfix_snippet( - "match", - "match expr {}", - &format!( - "match {receiver_text} {{\n Some(${{1:_}}) => {{$2}},\n None => {{$0}},\n}}" - ), - ) - .add_to(acc, ctx.db); - } - }, - None => { - postfix_snippet( - "match", - "match expr {}", - &format!("match {receiver_text} {{\n ${{1:_}} => {{$0}},\n}}"), - ) - .add_to(acc, ctx.db); - } - } - postfix_snippet("box", "Box::new(expr)", &format!("Box::new({receiver_text})")) .add_to(acc, ctx.db); postfix_snippet("dbg", "dbg!(expr)", &format!("dbg!({receiver_text})")).add_to(acc, ctx.db); // fixme @@ -233,15 +115,183 @@ pub(crate) fn complete_postfix( postfix_snippet("call", "function(expr)", &format!("${{1}}({receiver_text})")) .add_to(acc, ctx.db); - if let Some(parent) = dot_receiver_including_refs.syntax().parent().and_then(|p| p.parent()) { - if matches!(parent.kind(), STMT_LIST | EXPR_STMT) { - postfix_snippet("let", "let", &format!("let $0 = {receiver_text};")) - .add_to(acc, ctx.db); - postfix_snippet("letm", "let mut", &format!("let mut $0 = {receiver_text};")) - .add_to(acc, ctx.db); + let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty.strip_references()); + let mut is_in_cond = false; + if let Some(parent) = dot_receiver_including_refs.syntax().parent() { + if let Some(second_ancestor) = parent.parent() { + let sec_ancestor_kind = second_ancestor.kind(); + if let Some(expr) = >::cast(second_ancestor) { + is_in_cond = match expr { + Either::Left(it) => it.condition().is_some_and(|cond| *cond.syntax() == parent), + Either::Right(it) => { + it.condition().is_some_and(|cond| *cond.syntax() == parent) + } + } + } + match &try_enum { + Some(try_enum) if is_in_cond => match try_enum { + TryEnum::Result => { + postfix_snippet( + "let", + "let Ok(_)", + &format!("let Ok($0) = {receiver_text}"), + ) + .add_to(acc, ctx.db); + postfix_snippet( + "letm", + "let Ok(mut _)", + &format!("let Ok(mut $0) = {receiver_text}"), + ) + .add_to(acc, ctx.db); + } + TryEnum::Option => { + postfix_snippet( + "let", + "let Some(_)", + &format!("let Some($0) = {receiver_text}"), + ) + .add_to(acc, ctx.db); + postfix_snippet( + "letm", + "let Some(mut _)", + &format!("let Some(mut $0) = {receiver_text}"), + ) + .add_to(acc, ctx.db); + } + }, + _ if matches!(sec_ancestor_kind, STMT_LIST | EXPR_STMT) => { + postfix_snippet("let", "let", &format!("let $0 = {receiver_text};")) + .add_to(acc, ctx.db); + postfix_snippet("letm", "let mut", &format!("let mut $0 = {receiver_text};")) + .add_to(acc, ctx.db); + } + _ => (), + } } } + if !is_in_cond { + match try_enum { + Some(try_enum) => match try_enum { + TryEnum::Result => { + postfix_snippet( + "match", + "match expr {}", + &format!("match {receiver_text} {{\n Ok(${{1:_}}) => {{$2}},\n Err(${{3:_}}) => {{$0}},\n}}"), + ) + .add_to(acc, ctx.db); + } + TryEnum::Option => { + postfix_snippet( + "match", + "match expr {}", + &format!( + "match {receiver_text} {{\n Some(${{1:_}}) => {{$2}},\n None => {{$0}},\n}}" + ), + ) + .add_to(acc, ctx.db); + } + }, + None => { + postfix_snippet( + "match", + "match expr {}", + &format!("match {receiver_text} {{\n ${{1:_}} => {{$0}},\n}}"), + ) + .add_to(acc, ctx.db); + } + } + if let Some(try_enum) = &try_enum { + match try_enum { + TryEnum::Result => { + postfix_snippet( + "ifl", + "if let Ok {}", + &format!("if let Ok($1) = {receiver_text} {{\n $0\n}}"), + ) + .add_to(acc, ctx.db); + + postfix_snippet( + "lete", + "let Ok else {}", + &format!("let Ok($1) = {receiver_text} else {{\n $2\n}};\n$0"), + ) + .add_to(acc, ctx.db); + + postfix_snippet( + "while", + "while let Ok {}", + &format!("while let Ok($1) = {receiver_text} {{\n $0\n}}"), + ) + .add_to(acc, ctx.db); + } + TryEnum::Option => { + postfix_snippet( + "ifl", + "if let Some {}", + &format!("if let Some($1) = {receiver_text} {{\n $0\n}}"), + ) + .add_to(acc, ctx.db); + + postfix_snippet( + "lete", + "let Some else {}", + &format!("let Some($1) = {receiver_text} else {{\n $2\n}};\n$0"), + ) + .add_to(acc, ctx.db); + + postfix_snippet( + "while", + "while let Some {}", + &format!("while let Some($1) = {receiver_text} {{\n $0\n}}"), + ) + .add_to(acc, ctx.db); + } + } + } else if receiver_ty.is_bool() || receiver_ty.is_unknown() { + postfix_snippet("if", "if expr {}", &format!("if {receiver_text} {{\n $0\n}}")) + .add_to(acc, ctx.db); + postfix_snippet( + "while", + "while expr {}", + &format!("while {receiver_text} {{\n $0\n}}"), + ) + .add_to(acc, ctx.db); + postfix_snippet("not", "!expr", &format!("!{receiver_text}")).add_to(acc, ctx.db); + } else if let Some(trait_) = ctx.famous_defs().core_iter_IntoIterator() { + if receiver_ty.impls_trait(ctx.db, trait_, &[]) { + postfix_snippet( + "for", + "for ele in expr {}", + &format!("for ele in {receiver_text} {{\n $0\n}}"), + ) + .add_to(acc, ctx.db); + } + } + } + + let mut block_should_be_wrapped = true; + if dot_receiver.syntax().kind() == BLOCK_EXPR { + block_should_be_wrapped = false; + if let Some(parent) = dot_receiver.syntax().parent() { + if matches!(parent.kind(), IF_EXPR | WHILE_EXPR | LOOP_EXPR | FOR_EXPR) { + block_should_be_wrapped = true; + } + } + }; + { + let (open_brace, close_brace) = + if block_should_be_wrapped { ("{ ", " }") } else { ("", "") }; + let (open_paren, close_paren) = if is_in_cond { ("(", ")") } else { ("", "") }; + let unsafe_completion_string = + format!("{open_paren}unsafe {open_brace}{receiver_text}{close_brace}{close_paren}"); + postfix_snippet("unsafe", "unsafe {}", &unsafe_completion_string).add_to(acc, ctx.db); + + let const_completion_string = + format!("{open_paren}const {open_brace}{receiver_text}{close_brace}{close_paren}"); + postfix_snippet("const", "const {}", &const_completion_string).add_to(acc, ctx.db); + } + if let ast::Expr::Literal(literal) = dot_receiver_including_refs.clone() { if let Some(literal_text) = ast::String::cast(literal.token()) { add_format_like_completions(acc, ctx, &dot_receiver_including_refs, cap, &literal_text); @@ -567,6 +617,54 @@ fn main() { ); } + #[test] + fn option_iflet_cond() { + check( + r#" +//- minicore: option +fn main() { + let bar = Some(true); + if bar.$0 +} +"#, + expect![[r#" + me and(…) fn(self, Option) -> Option + me as_ref() const fn(&self) -> Option<&T> + me ok_or(…) const fn(self, E) -> Result + me unwrap() const fn(self) -> T + me unwrap_or(…) fn(self, T) -> T + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn let let Some(_) + sn letm let Some(mut _) + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} + "#]], + ); + check_edit( + "let", + r#" +//- minicore: option +fn main() { + let bar = Some(true); + if bar.$0 +} +"#, + r#" +fn main() { + let bar = Some(true); + if let Some($0) = bar +} +"#, + ); + } + #[test] fn option_letelse() { check_edit( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs index c18aab007b2c..36f38a70db63 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs @@ -88,7 +88,7 @@ pub(crate) fn complete_record_expr_fields( pub(crate) fn add_default_update( acc: &mut Completions, ctx: &CompletionContext<'_>, - ty: Option, + ty: Option>, ) { let default_trait = ctx.famous_defs().core_default_Default(); let impls_default_trait = default_trait @@ -117,7 +117,7 @@ pub(crate) fn add_default_update( fn complete_fields( acc: &mut Completions, ctx: &CompletionContext<'_>, - missing_fields: Vec<(hir::Field, hir::Type)>, + missing_fields: Vec<(hir::Field, hir::Type<'_>)>, ) { for (field, ty) in missing_fields { // This should call something else, we shouldn't be synthesizing a DotAccess here diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs index 31aae1167622..ead9852eff53 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs @@ -11,8 +11,8 @@ use crate::{ pub(crate) fn complete_expr_snippet( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, - &PathExprCtx { in_block_expr, .. }: &PathExprCtx, + path_ctx: &PathCompletionCtx<'_>, + &PathExprCtx { in_block_expr, .. }: &PathExprCtx<'_>, ) { if !matches!(path_ctx.qualified, Qualified::No) { return; @@ -51,7 +51,7 @@ macro_rules! $1 { pub(crate) fn complete_item_snippet( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, kind: &ItemListKind, ) { if !matches!(path_ctx.qualified, Qualified::No) { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs index 79db705af495..7c38c7d8ce44 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs @@ -12,7 +12,7 @@ use crate::{ pub(crate) fn complete_type_path( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, + path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx<'_>, location: &TypeLocation, ) { let _p = tracing::info_span!("complete_type_path").entered(); @@ -220,7 +220,7 @@ pub(crate) fn complete_type_path( pub(crate) fn complete_ascribed_type( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, ascription: &TypeAscriptionTarget, ) -> Option<()> { if !path_ctx.is_trivial_path() { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs index 4d6d0b758a38..d2ab193ec3df 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs @@ -13,7 +13,7 @@ use crate::{ pub(crate) fn complete_use_path( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx @ PathCompletionCtx { qualified, use_tree_parent, .. }: &PathCompletionCtx, + path_ctx @ PathCompletionCtx { qualified, use_tree_parent, .. }: &PathCompletionCtx<'_>, name_ref: &Option, ) { match qualified { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/vis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/vis.rs index d15c35ac8499..38761f77a2c5 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/vis.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/vis.rs @@ -8,7 +8,7 @@ use crate::{ pub(crate) fn complete_vis_path( acc: &mut Completions, ctx: &CompletionContext<'_>, - path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, + path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx<'_>, &has_in_token: &bool, ) { match qualified { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs index 5287627790ae..cfd7f80d40b3 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs @@ -65,13 +65,13 @@ impl QualifierCtx { /// The state of the path we are currently completing. #[derive(Debug)] -pub(crate) struct PathCompletionCtx { +pub(crate) struct PathCompletionCtx<'db> { /// If this is a call with () already there (or {} in case of record patterns) pub(crate) has_call_parens: bool, /// If this has a macro call bang ! pub(crate) has_macro_bang: bool, /// The qualifier of the current path. - pub(crate) qualified: Qualified, + pub(crate) qualified: Qualified<'db>, /// The parent of the path we are completing. pub(crate) parent: Option, #[allow(dead_code)] @@ -79,14 +79,14 @@ pub(crate) struct PathCompletionCtx { pub(crate) path: ast::Path, /// The path of which we are completing the segment in the original file pub(crate) original_path: Option, - pub(crate) kind: PathKind, + pub(crate) kind: PathKind<'db>, /// Whether the path segment has type args or not. pub(crate) has_type_args: bool, /// Whether the qualifier comes from a use tree parent or not pub(crate) use_tree_parent: bool, } -impl PathCompletionCtx { +impl PathCompletionCtx<'_> { pub(crate) fn is_trivial_path(&self) -> bool { matches!( self, @@ -104,9 +104,9 @@ impl PathCompletionCtx { /// The kind of path we are completing right now. #[derive(Debug, PartialEq, Eq)] -pub(crate) enum PathKind { +pub(crate) enum PathKind<'db> { Expr { - expr_ctx: PathExprCtx, + expr_ctx: PathExprCtx<'db>, }, Type { location: TypeLocation, @@ -140,7 +140,7 @@ pub(crate) struct AttrCtx { } #[derive(Debug, PartialEq, Eq)] -pub(crate) struct PathExprCtx { +pub(crate) struct PathExprCtx<'db> { pub(crate) in_block_expr: bool, pub(crate) in_breakable: BreakableKind, pub(crate) after_if_expr: bool, @@ -152,7 +152,7 @@ pub(crate) struct PathExprCtx { /// The surrounding RecordExpression we are completing a functional update pub(crate) is_func_update: Option, pub(crate) self_param: Option, - pub(crate) innermost_ret_ty: Option, + pub(crate) innermost_ret_ty: Option>, pub(crate) impl_: Option, /// Whether this expression occurs in match arm guard position: before the /// fat arrow token @@ -241,7 +241,7 @@ pub(crate) enum ItemListKind { } #[derive(Debug)] -pub(crate) enum Qualified { +pub(crate) enum Qualified<'db> { No, With { path: ast::Path, @@ -260,7 +260,7 @@ pub(crate) enum Qualified { }, /// <_>:: TypeAnchor { - ty: Option, + ty: Option>, trait_: Option, }, /// Whether the path is an absolute path @@ -341,17 +341,17 @@ pub(crate) enum NameKind { /// The state of the NameRef we are completing. #[derive(Debug)] -pub(crate) struct NameRefContext { +pub(crate) struct NameRefContext<'db> { /// NameRef syntax in the original file pub(crate) nameref: Option, - pub(crate) kind: NameRefKind, + pub(crate) kind: NameRefKind<'db>, } /// The kind of the NameRef we are completing. #[derive(Debug)] -pub(crate) enum NameRefKind { - Path(PathCompletionCtx), - DotAccess(DotAccess), +pub(crate) enum NameRefKind<'db> { + Path(PathCompletionCtx<'db>), + DotAccess(DotAccess<'db>), /// Position where we are only interested in keyword completions Keyword(ast::Item), /// The record expression this nameref is a field of and whether a dot precedes the completion identifier. @@ -365,9 +365,9 @@ pub(crate) enum NameRefKind { /// The identifier we are currently completing. #[derive(Debug)] -pub(crate) enum CompletionAnalysis { +pub(crate) enum CompletionAnalysis<'db> { Name(NameContext), - NameRef(NameRefContext), + NameRef(NameRefContext<'db>), Lifetime(LifetimeContext), /// The string the cursor is currently inside String { @@ -386,9 +386,9 @@ pub(crate) enum CompletionAnalysis { /// Information about the field or method access we are completing. #[derive(Debug)] -pub(crate) struct DotAccess { +pub(crate) struct DotAccess<'db> { pub(crate) receiver: Option, - pub(crate) receiver_ty: Option, + pub(crate) receiver_ty: Option>, pub(crate) kind: DotAccessKind, pub(crate) ctx: DotAccessExprCtx, } @@ -457,7 +457,7 @@ pub(crate) struct CompletionContext<'a> { /// This is usually the parameter name of the function argument we are completing. pub(crate) expected_name: Option, /// The expected type of what we are completing. - pub(crate) expected_type: Option, + pub(crate) expected_type: Option>, pub(crate) qualifier_ctx: QualifierCtx, @@ -608,7 +608,7 @@ impl CompletionContext<'_> { pub(crate) fn iterate_path_candidates( &self, - ty: &hir::Type, + ty: &hir::Type<'_>, mut cb: impl FnMut(hir::AssocItem), ) { let mut seen = FxHashSet::default(); @@ -695,12 +695,12 @@ impl CompletionContext<'_> { } // CompletionContext construction -impl<'a> CompletionContext<'a> { +impl<'db> CompletionContext<'db> { pub(crate) fn new( - db: &'a RootDatabase, + db: &'db RootDatabase, position @ FilePosition { file_id, offset }: FilePosition, - config: &'a CompletionConfig<'a>, - ) -> Option<(CompletionContext<'a>, CompletionAnalysis)> { + config: &'db CompletionConfig<'db>, + ) -> Option<(CompletionContext<'db>, CompletionAnalysis<'db>)> { let _p = tracing::info_span!("CompletionContext::new").entered(); let sema = Semantics::new(db); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs index 7a2230b3e361..6e3a76f346a8 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs @@ -38,9 +38,9 @@ struct ExpansionResult { derive_ctx: Option<(SyntaxNode, SyntaxNode, TextSize, ast::Attr)>, } -pub(super) struct AnalysisResult { - pub(super) analysis: CompletionAnalysis, - pub(super) expected: (Option, Option), +pub(super) struct AnalysisResult<'db> { + pub(super) analysis: CompletionAnalysis<'db>, + pub(super) expected: (Option>, Option), pub(super) qualifier_ctx: QualifierCtx, /// the original token of the expanded file pub(super) token: SyntaxToken, @@ -48,13 +48,13 @@ pub(super) struct AnalysisResult { pub(super) original_offset: TextSize, } -pub(super) fn expand_and_analyze( - sema: &Semantics<'_, RootDatabase>, +pub(super) fn expand_and_analyze<'db>( + sema: &Semantics<'db, RootDatabase>, original_file: InFile, speculative_file: SyntaxNode, offset: TextSize, original_token: &SyntaxToken, -) -> Option { +) -> Option> { // as we insert after the offset, right biased will *always* pick the identifier no matter // if there is an ident already typed or not let fake_ident_token = speculative_file.token_at_offset(offset).right_biased()?; @@ -432,12 +432,13 @@ fn expand( /// Fill the completion context, this is what does semantic reasoning about the surrounding context /// of the completion location. -fn analyze( - sema: &Semantics<'_, RootDatabase>, +fn analyze<'db>( + sema: &Semantics<'db, RootDatabase>, expansion_result: ExpansionResult, original_token: &SyntaxToken, self_token: &SyntaxToken, -) -> Option<(CompletionAnalysis, (Option, Option), QualifierCtx)> { +) -> Option<(CompletionAnalysis<'db>, (Option>, Option), QualifierCtx)> +{ let _p = tracing::info_span!("CompletionContext::analyze").entered(); let ExpansionResult { original_file, @@ -555,17 +556,17 @@ fn analyze( } /// Calculate the expected type and name of the cursor position. -fn expected_type_and_name( - sema: &Semantics<'_, RootDatabase>, +fn expected_type_and_name<'db>( + sema: &Semantics<'db, RootDatabase>, token: &SyntaxToken, name_like: &ast::NameLike, -) -> (Option, Option) { +) -> (Option>, Option) { let mut node = match token.parent() { Some(it) => it, None => return (None, None), }; - let strip_refs = |mut ty: Type| match name_like { + let strip_refs = |mut ty: Type<'db>| match name_like { ast::NameLike::NameRef(n) => { let p = match n.syntax().parent() { Some(it) => it, @@ -805,13 +806,13 @@ fn classify_name( Some(NameContext { name, kind }) } -fn classify_name_ref( - sema: &Semantics<'_, RootDatabase>, +fn classify_name_ref<'db>( + sema: &Semantics<'db, RootDatabase>, original_file: &SyntaxNode, name_ref: ast::NameRef, original_offset: TextSize, parent: SyntaxNode, -) -> Option<(NameRefContext, QualifierCtx)> { +) -> Option<(NameRefContext<'db>, QualifierCtx)> { let nameref = find_node_at_offset(original_file, original_offset); let make_res = |kind| (NameRefContext { nameref: nameref.clone(), kind }, Default::default()); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs index 19cdef30bd96..dcaac3997b27 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -502,7 +502,7 @@ pub(crate) struct Builder { impl Builder { pub(crate) fn from_resolution( ctx: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, local_name: hir::Name, resolution: hir::ScopeDef, ) -> Self { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 00c0b470f987..c6b8af3c79a2 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -122,10 +122,10 @@ impl<'a> RenderContext<'a> { pub(crate) fn render_field( ctx: RenderContext<'_>, - dot_access: &DotAccess, + dot_access: &DotAccess<'_>, receiver: Option, field: hir::Field, - ty: &hir::Type, + ty: &hir::Type<'_>, ) -> CompletionItem { let db = ctx.db(); let is_deprecated = ctx.is_deprecated(field); @@ -204,7 +204,7 @@ pub(crate) fn render_tuple_field( ctx: RenderContext<'_>, receiver: Option, field: usize, - ty: &hir::Type, + ty: &hir::Type<'_>, ) -> CompletionItem { let mut item = CompletionItem::new( SymbolKind::Field, @@ -241,7 +241,7 @@ pub(crate) fn render_type_inference( pub(crate) fn render_path_resolution( ctx: RenderContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, local_name: hir::Name, resolution: ScopeDef, ) -> Builder { @@ -259,7 +259,7 @@ pub(crate) fn render_pattern_resolution( pub(crate) fn render_resolution_with_import( ctx: RenderContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, import_edit: LocatedImport, ) -> Option { let resolution = ScopeDef::from(import_edit.original_item); @@ -282,10 +282,10 @@ pub(crate) fn render_resolution_with_import_pat( pub(crate) fn render_expr( ctx: &CompletionContext<'_>, - expr: &hir::term_search::Expr, + expr: &hir::term_search::Expr<'_>, ) -> Option { let mut i = 1; - let mut snippet_formatter = |ty: &hir::Type| { + let mut snippet_formatter = |ty: &hir::Type<'_>| { let arg_name = ty .as_adt() .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str())) @@ -295,7 +295,7 @@ pub(crate) fn render_expr( res }; - let mut label_formatter = |ty: &hir::Type| { + let mut label_formatter = |ty: &hir::Type<'_>| { ty.as_adt() .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str())) .unwrap_or_else(|| String::from("...")) @@ -391,7 +391,7 @@ fn render_resolution_pat( fn render_resolution_path( ctx: RenderContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, local_name: hir::Name, import_to_add: Option, resolution: ScopeDef, @@ -460,7 +460,7 @@ fn render_resolution_path( } } - let mut set_item_relevance = |ty: Type| { + let mut set_item_relevance = |ty: Type<'_>| { if !ty.is_unknown() { item.detail(ty.display(db, krate).to_string()); } @@ -593,8 +593,8 @@ fn scope_def_is_deprecated(ctx: &RenderContext<'_>, resolution: ScopeDef) -> boo // FIXME: This checks types without possible coercions which some completions might want to do fn match_types( ctx: &CompletionContext<'_>, - ty1: &hir::Type, - ty2: &hir::Type, + ty1: &hir::Type<'_>, + ty2: &hir::Type<'_>, ) -> Option { if ty1 == ty2 { Some(CompletionRelevanceTypeMatch::Exact) @@ -607,7 +607,7 @@ fn match_types( fn compute_type_match( ctx: &CompletionContext<'_>, - completion_ty: &hir::Type, + completion_ty: &hir::Type<'_>, ) -> Option { let expected_type = ctx.expected_type.as_ref()?; @@ -626,7 +626,7 @@ fn compute_exact_name_match(ctx: &CompletionContext<'_>, completion_name: &str) fn compute_ref_match( ctx: &CompletionContext<'_>, - completion_ty: &hir::Type, + completion_ty: &hir::Type<'_>, ) -> Option { let expected_type = ctx.expected_type.as_ref()?; let expected_without_ref = expected_type.remove_ref(); @@ -658,8 +658,8 @@ fn compute_ref_match( fn path_ref_match( completion: &CompletionContext<'_>, - path_ctx: &PathCompletionCtx, - ty: &hir::Type, + path_ctx: &PathCompletionCtx<'_>, + ty: &hir::Type<'_>, item: &mut Builder, ) { if let Some(original_path) = &path_ctx.original_path { @@ -733,7 +733,7 @@ mod tests { ) { let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None); actual.retain(|it| kinds.contains(&it.kind)); - actual.sort_by_key(|it| cmp::Reverse(it.relevance.score())); + actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone())); check_relevance_(actual, expect); } @@ -743,7 +743,7 @@ mod tests { actual.retain(|it| it.kind != CompletionItemKind::Snippet); actual.retain(|it| it.kind != CompletionItemKind::Keyword); actual.retain(|it| it.kind != CompletionItemKind::BuiltinType); - actual.sort_by_key(|it| cmp::Reverse(it.relevance.score())); + actual.sort_by_key(|it| (cmp::Reverse(it.relevance.score()), it.label.primary.clone())); check_relevance_(actual, expect); } @@ -824,9 +824,9 @@ fn main() { st dep::test_mod_b::Struct {…} dep::test_mod_b::Struct { } [type_could_unify] ex dep::test_mod_b::Struct { } [type_could_unify] st Struct Struct [type_could_unify+requires_import] + md dep [] fn main() fn() [] fn test(…) fn(Struct) [] - md dep [] st Struct Struct [requires_import] "#]], ); @@ -862,9 +862,9 @@ fn main() { "#, expect![[r#" un Union Union [type_could_unify+requires_import] + md dep [] fn main() fn() [] fn test(…) fn(Union) [] - md dep [] en Union Union [requires_import] "#]], ); @@ -900,9 +900,9 @@ fn main() { ev dep::test_mod_b::Enum::variant dep::test_mod_b::Enum::variant [type_could_unify] ex dep::test_mod_b::Enum::variant [type_could_unify] en Enum Enum [type_could_unify+requires_import] + md dep [] fn main() fn() [] fn test(…) fn(Enum) [] - md dep [] en Enum Enum [requires_import] "#]], ); @@ -937,9 +937,9 @@ fn main() { expect![[r#" ev dep::test_mod_b::Enum::Variant dep::test_mod_b::Enum::Variant [type_could_unify] ex dep::test_mod_b::Enum::Variant [type_could_unify] + md dep [] fn main() fn() [] fn test(…) fn(Enum) [] - md dep [] "#]], ); } @@ -967,9 +967,9 @@ fn main() { } "#, expect![[r#" + md dep [] fn main() fn() [] fn test(…) fn(fn(usize) -> i32) [] - md dep [] fn function fn(usize) -> i32 [requires_import] fn function(…) fn(isize) -> i32 [requires_import] "#]], @@ -1000,9 +1000,9 @@ fn main() { "#, expect![[r#" ct CONST i32 [type_could_unify+requires_import] + md dep [] fn main() fn() [] fn test(…) fn(i32) [] - md dep [] ct CONST i64 [requires_import] "#]], ); @@ -1032,9 +1032,9 @@ fn main() { "#, expect![[r#" sc STATIC i32 [type_could_unify+requires_import] + md dep [] fn main() fn() [] fn test(…) fn(i32) [] - md dep [] sc STATIC i64 [requires_import] "#]], ); @@ -1090,8 +1090,8 @@ fn func(input: Struct) { } "#, expect![[r#" - st Struct Struct [type] st Self Self [type] + st Struct Struct [type] sp Self Struct [type] st Struct Struct [type] ex Struct [type] @@ -1119,9 +1119,9 @@ fn main() { "#, expect![[r#" lc input bool [type+name+local] + ex false [type] ex input [type] ex true [type] - ex false [type] lc inputbad i32 [local] fn main() fn() [] fn test(…) fn(bool) [] @@ -2088,9 +2088,9 @@ fn f() { A { bar: b$0 }; } "#, expect![[r#" fn bar() fn() -> u8 [type+name] + ex bar() [type] fn baz() fn() -> u8 [type] ex baz() [type] - ex bar() [type] st A A [] fn f() fn() [] "#]], @@ -2199,8 +2199,8 @@ fn main() { lc s S [type+name+local] st S S [type] st S S [type] - ex s [type] ex S [type] + ex s [type] fn foo(…) fn(&mut S) [] fn main() fn() [] "#]], @@ -2218,8 +2218,8 @@ fn main() { st S S [type] lc ssss S [type+local] st S S [type] - ex ssss [type] ex S [type] + ex ssss [type] fn foo(…) fn(&mut S) [] fn main() fn() [] "#]], @@ -2252,11 +2252,11 @@ fn main() { ex Foo [type] lc foo &Foo [local] lc *foo [type+local] - fn bar(…) fn(Foo) [] - fn main() fn() [] - md core [] tt Clone [] tt Copy [] + fn bar(…) fn(Foo) [] + md core [] + fn main() fn() [] "#]], ); } @@ -2297,9 +2297,9 @@ fn main() { st &S [type] st T T [] st &T [type] + md core [] fn foo(…) fn(&S) [] fn main() fn() [] - md core [] "#]], ) } @@ -2346,9 +2346,9 @@ fn main() { st &mut S [type] st T T [] st &mut T [type] + md core [] fn foo(…) fn(&mut S) [] fn main() fn() [] - md core [] "#]], ) } @@ -2364,8 +2364,8 @@ fn foo(bar: u32) { } "#, expect![[r#" - lc baz i32 [local] lc bar u32 [local] + lc baz i32 [local] fn foo(…) fn(u32) [] "#]], ); @@ -2449,9 +2449,9 @@ fn main() { st &T [type] fn bar() fn() -> T [] fn &bar() [type] + md core [] fn foo(…) fn(&S) [] fn main() fn() [] - md core [] "#]], ) } @@ -2702,8 +2702,8 @@ fn test() { fn fn_builder() fn() -> FooBuilder [type_could_unify] fn fn_ctr_wrapped() fn() -> Option> [type_could_unify] fn fn_ctr_wrapped_2() fn() -> Result, u32> [type_could_unify] - me fn_returns_unit(…) fn(&self) [type_could_unify] fn fn_other() fn() -> Option [type_could_unify] + me fn_returns_unit(…) fn(&self) [type_could_unify] "#]], ); } @@ -2965,12 +2965,12 @@ fn foo() { ev Foo::B Foo::B [type_could_unify] ev Foo::A(…) Foo::A(T) [type_could_unify] lc foo Foo [type+local] - ex foo [type] ex Foo::B [type] + ex foo [type] en Foo Foo<{unknown}> [type_could_unify] - fn foo() fn() [] fn bar() fn() -> Foo [] fn baz() fn() -> Foo [] + fn foo() fn() [] "#]], ); } @@ -3000,19 +3000,19 @@ fn main() { expect![[r#" sn not !expr [snippet] me not() fn(self) -> ::Output [type_could_unify+requires_import] - sn if if expr {} [] - sn while while expr {} [] - sn ref &expr [] - sn refm &mut expr [] - sn deref *expr [] - sn unsafe unsafe {} [] - sn const const {} [] - sn match match expr {} [] sn box Box::new(expr) [] + sn call function(expr) [] + sn const const {} [] sn dbg dbg!(expr) [] sn dbgr dbg!(&expr) [] - sn call function(expr) [] + sn deref *expr [] + sn if if expr {} [] + sn match match expr {} [] + sn ref &expr [] + sn refm &mut expr [] sn return return expr [] + sn unsafe unsafe {} [] + sn while while expr {} [] "#]], ); } @@ -3033,19 +3033,19 @@ fn main() { &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)], expect![[r#" me f() fn(&self) [] - sn ref &expr [] - sn refm &mut expr [] - sn deref *expr [] - sn unsafe unsafe {} [] - sn const const {} [] - sn match match expr {} [] sn box Box::new(expr) [] + sn call function(expr) [] + sn const const {} [] sn dbg dbg!(expr) [] sn dbgr dbg!(&expr) [] - sn call function(expr) [] + sn deref *expr [] sn let let [] sn letm let mut [] + sn match match expr {} [] + sn ref &expr [] + sn refm &mut expr [] sn return return expr [] + sn unsafe unsafe {} [] "#]], ); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs index 2fe517fa8cd0..7669aec8f535 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs @@ -22,13 +22,13 @@ use crate::{ #[derive(Debug)] enum FuncKind<'ctx> { - Function(&'ctx PathCompletionCtx), - Method(&'ctx DotAccess, Option), + Function(&'ctx PathCompletionCtx<'ctx>), + Method(&'ctx DotAccess<'ctx>, Option), } pub(crate) fn render_fn( ctx: RenderContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, local_name: Option, func: hir::Function, ) -> Builder { @@ -38,7 +38,7 @@ pub(crate) fn render_fn( pub(crate) fn render_method( ctx: RenderContext<'_>, - dot_access: &DotAccess, + dot_access: &DotAccess<'_>, receiver: Option, local_name: Option, func: hir::Function, @@ -186,8 +186,8 @@ fn render( fn compute_return_type_match( db: &dyn HirDatabase, ctx: &RenderContext<'_>, - self_type: hir::Type, - ret_type: &hir::Type, + self_type: hir::Type<'_>, + ret_type: &hir::Type<'_>, ) -> CompletionRelevanceReturnType { if match_types(ctx.completion, &self_type, ret_type).is_some() { // fn([..]) -> Self @@ -217,8 +217,8 @@ pub(super) fn add_call_parens<'b>( name: SmolStr, escaped_name: SmolStr, self_param: Option, - params: Vec, - ret_type: &hir::Type, + params: Vec>, + ret_type: &hir::Type<'_>, ) -> &'b mut Builder { cov_mark::hit!(inserts_parens_for_function_calls); @@ -288,7 +288,7 @@ pub(super) fn add_call_parens<'b>( builder.label(SmolStr::from_iter([&name, label_suffix])).insert_snippet(cap, snippet) } -fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'static str { +fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type<'_>) -> &'static str { if let Some(derefed_ty) = ty.remove_ref() { for (name, local) in ctx.locals.iter().sorted_by_key(|&(k, _)| k.clone()) { if name.as_str() == arg { @@ -369,12 +369,12 @@ fn params_display(ctx: &CompletionContext<'_>, detail: &mut String, func: hir::F } } -fn params( - ctx: &CompletionContext<'_>, +fn params<'db>( + ctx: &CompletionContext<'db>, func: hir::Function, func_kind: &FuncKind<'_>, has_dot_receiver: bool, -) -> Option<(Option, Vec)> { +) -> Option<(Option, Vec>)> { ctx.config.callable.as_ref()?; // Don't add parentheses if the expected type is a function reference with the same signature. diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs index 5a9e35a7290b..6c89e49f94e8 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs @@ -21,7 +21,7 @@ use crate::{ pub(crate) fn render_variant_lit( ctx: RenderContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, local_name: Option, variant: hir::Variant, path: Option, @@ -35,7 +35,7 @@ pub(crate) fn render_variant_lit( pub(crate) fn render_struct_literal( ctx: RenderContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, strukt: hir::Struct, path: Option, local_name: Option, @@ -49,7 +49,7 @@ pub(crate) fn render_struct_literal( fn render( ctx @ RenderContext { completion, .. }: RenderContext<'_>, - path_ctx: &PathCompletionCtx, + path_ctx: &PathCompletionCtx<'_>, thing: Variant, name: hir::Name, path: Option, @@ -194,7 +194,7 @@ impl Variant { } } - fn ty(self, db: &dyn HirDatabase) -> hir::Type { + fn ty(self, db: &dyn HirDatabase) -> hir::Type<'_> { match self { Variant::Struct(it) => it.ty(db), Variant::EnumVariant(it) => it.parent_enum(db).ty(db), diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs index 4674dae03144..35fe407b2e68 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs @@ -12,7 +12,7 @@ use crate::{ pub(crate) fn render_macro( ctx: RenderContext<'_>, - PathCompletionCtx { kind, has_macro_bang, has_call_parens, .. }: &PathCompletionCtx, + PathCompletionCtx { kind, has_macro_bang, has_call_parens, .. }: &PathCompletionCtx<'_>, name: hir::Name, macro_: hir::Macro, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs index dcc51a86a8ed..60ec1128233e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs @@ -46,7 +46,7 @@ pub(crate) fn render_struct_pat( pub(crate) fn render_variant_pat( ctx: RenderContext<'_>, pattern_ctx: &PatternContext, - path_ctx: Option<&PathCompletionCtx>, + path_ctx: Option<&PathCompletionCtx<'_>>, variant: hir::Variant, local_name: Option, path: Option<&hir::ModPath>, @@ -109,7 +109,7 @@ fn build_completion( lookup: SmolStr, pat: String, def: impl HasDocs + Copy, - adt_ty: hir::Type, + adt_ty: hir::Type<'_>, // Missing in context of match statement completions is_variant_missing: bool, ) -> CompletionItem { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index b46e4c32061b..b2d18b796f19 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -1474,20 +1474,18 @@ fn main() { } "#, expect![[r#" + me foo() fn(&self) sn box Box::new(expr) sn call function(expr) sn const const {} sn dbg dbg!(expr) sn dbgr dbg!(&expr) sn deref *expr - sn if if expr {} sn match match expr {} - sn not !expr sn ref &expr sn refm &mut expr sn return return expr sn unsafe unsafe {} - sn while while expr {} "#]], ); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/visibility.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/visibility.rs index 4b5a0ac1c2b9..b404011dfe65 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/visibility.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/visibility.rs @@ -1,7 +1,7 @@ //! Completion tests for visibility modifiers. use expect_test::expect; -use crate::tests::{check, check_with_trigger_character}; +use crate::tests::{check, check_with_private_editable, check_with_trigger_character}; #[test] fn empty_pub() { @@ -78,3 +78,90 @@ mod bar {} "#]], ); } + +#[test] +fn use_inner_public_function() { + check( + r#" +//- /inner.rs crate:inner +pub fn inner_public() {} +fn inner_private() {} +//- /foo.rs crate:foo deps:inner +use inner::inner_public; +pub fn outer_public() {} +//- /lib.rs crate:lib deps:foo +fn x() { + foo::$0 +} + "#, + expect![[r#" + fn outer_public() fn() + "#]], + ); +} + +#[test] +fn pub_use_inner_public_function() { + check( + r#" +//- /inner.rs crate:inner +pub fn inner_public() {} +fn inner_private() {} +//- /foo.rs crate:foo deps:inner +pub use inner::inner_public; +pub fn outer_public() {} +//- /lib.rs crate:lib deps:foo +fn x() { + foo::$0 +} + "#, + expect![[r#" + fn inner_public() fn() + fn outer_public() fn() + "#]], + ); +} + +#[test] +fn use_inner_public_function_private_editable() { + check_with_private_editable( + r#" +//- /inner.rs crate:inner +pub fn inner_public() {} +fn inner_private() {} +//- /foo.rs crate:foo deps:inner +use inner::inner_public; +pub fn outer_public() {} +//- /lib.rs crate:lib deps:foo +fn x() { + foo::$0 +} + "#, + expect![[r#" + fn inner_public() fn() + fn outer_public() fn() + "#]], + ); +} + +#[test] +fn pub_use_inner_public_function_private_editable() { + check_with_private_editable( + r#" +//- /inner.rs crate:inner +pub fn inner_public() {} +fn inner_private() {} +//- /foo.rs crate:foo deps:inner +pub use inner::inner_public; +pub fn outer_public() {} +//- /lib.rs crate:lib deps:foo +fn x() { + foo::$0 +} + "#, + expect![[r#" + fn inner_public() fn() + fn outer_public() fn() + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs b/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs index 7b5723f37f76..9edfc113f764 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs @@ -13,21 +13,21 @@ use syntax::{ use crate::RootDatabase; #[derive(Debug)] -pub struct ActiveParameter { - pub ty: Type, +pub struct ActiveParameter<'db> { + pub ty: Type<'db>, pub src: Option>>, } -impl ActiveParameter { +impl<'db> ActiveParameter<'db> { /// Returns information about the call argument this token is part of. - pub fn at_token(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> Option { + pub fn at_token(sema: &Semantics<'db, RootDatabase>, token: SyntaxToken) -> Option { let (signature, active_parameter) = callable_for_token(sema, token)?; Self::from_signature_and_active_parameter(sema, signature, active_parameter) } /// Returns information about the call argument this token is part of. pub fn at_arg( - sema: &Semantics<'_, RootDatabase>, + sema: &'db Semantics<'db, RootDatabase>, list: ast::ArgList, at: TextSize, ) -> Option { @@ -36,8 +36,8 @@ impl ActiveParameter { } fn from_signature_and_active_parameter( - sema: &Semantics<'_, RootDatabase>, - signature: hir::Callable, + sema: &Semantics<'db, RootDatabase>, + signature: hir::Callable<'db>, active_parameter: Option, ) -> Option { let idx = active_parameter?; @@ -63,10 +63,10 @@ impl ActiveParameter { } /// Returns a [`hir::Callable`] this token is a part of and its argument index of said callable. -pub fn callable_for_token( - sema: &Semantics<'_, RootDatabase>, +pub fn callable_for_token<'db>( + sema: &Semantics<'db, RootDatabase>, token: SyntaxToken, -) -> Option<(hir::Callable, Option)> { +) -> Option<(hir::Callable<'db>, Option)> { let offset = token.text_range().start(); // Find the calling expression and its NameRef let parent = token.parent()?; @@ -79,21 +79,21 @@ pub fn callable_for_token( } /// Returns a [`hir::Callable`] this token is a part of and its argument index of said callable. -pub fn callable_for_arg_list( - sema: &Semantics<'_, RootDatabase>, +pub fn callable_for_arg_list<'db>( + sema: &Semantics<'db, RootDatabase>, arg_list: ast::ArgList, at: TextSize, -) -> Option<(hir::Callable, Option)> { +) -> Option<(hir::Callable<'db>, Option)> { debug_assert!(arg_list.syntax().text_range().contains(at)); let callable = arg_list.syntax().parent().and_then(ast::CallableExpr::cast)?; callable_for_node(sema, &callable, at) } -pub fn callable_for_node( - sema: &Semantics<'_, RootDatabase>, +pub fn callable_for_node<'db>( + sema: &Semantics<'db, RootDatabase>, calling_node: &ast::CallableExpr, offset: TextSize, -) -> Option<(hir::Callable, Option)> { +) -> Option<(hir::Callable<'db>, Option)> { let callable = match calling_node { ast::CallableExpr::Call(call) => sema.resolve_expr_as_callable(&call.expr()?), ast::CallableExpr::MethodCall(call) => sema.resolve_method_call_as_callable(call), diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index d5db1c481b69..a4a140ec57aa 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -385,17 +385,17 @@ fn find_std_module( // FIXME: IdentClass as a name no longer fits #[derive(Debug)] -pub enum IdentClass { - NameClass(NameClass), - NameRefClass(NameRefClass), +pub enum IdentClass<'db> { + NameClass(NameClass<'db>), + NameRefClass(NameRefClass<'db>), Operator(OperatorClass), } -impl IdentClass { +impl<'db> IdentClass<'db> { pub fn classify_node( - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, node: &SyntaxNode, - ) -> Option { + ) -> Option> { match_ast! { match node { ast::Name(name) => NameClass::classify(sema, &name).map(IdentClass::NameClass), @@ -418,23 +418,23 @@ impl IdentClass { } pub fn classify_token( - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, token: &SyntaxToken, - ) -> Option { + ) -> Option> { let parent = token.parent()?; Self::classify_node(sema, &parent) } pub fn classify_lifetime( - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, lifetime: &ast::Lifetime, - ) -> Option { + ) -> Option> { NameRefClass::classify_lifetime(sema, lifetime) .map(IdentClass::NameRefClass) .or_else(|| NameClass::classify_lifetime(sema, lifetime).map(IdentClass::NameClass)) } - pub fn definitions(self) -> ArrayVec<(Definition, Option), 2> { + pub fn definitions(self) -> ArrayVec<(Definition, Option>), 2> { let mut res = ArrayVec::new(); match self { IdentClass::NameClass(NameClass::Definition(it) | NameClass::ConstReference(it)) => { @@ -518,7 +518,7 @@ impl IdentClass { /// /// A model special case is `None` constant in pattern. #[derive(Debug)] -pub enum NameClass { +pub enum NameClass<'db> { Definition(Definition), /// `None` in `if let None = Some(82) {}`. /// Syntactically, it is a name, but semantically it is a reference. @@ -528,11 +528,11 @@ pub enum NameClass { PatFieldShorthand { local_def: Local, field_ref: Field, - adt_subst: GenericSubstitution, + adt_subst: GenericSubstitution<'db>, }, } -impl NameClass { +impl<'db> NameClass<'db> { /// `Definition` defined by this name. pub fn defined(self) -> Option { let res = match self { @@ -545,7 +545,10 @@ impl NameClass { Some(res) } - pub fn classify(sema: &Semantics<'_, RootDatabase>, name: &ast::Name) -> Option { + pub fn classify( + sema: &Semantics<'db, RootDatabase>, + name: &ast::Name, + ) -> Option> { let _p = tracing::info_span!("NameClass::classify").entered(); let parent = name.syntax().parent()?; @@ -597,10 +600,10 @@ impl NameClass { Some(definition) } - fn classify_ident_pat( - sema: &Semantics<'_, RootDatabase>, + fn classify_ident_pat<'db>( + sema: &Semantics<'db, RootDatabase>, ident_pat: ast::IdentPat, - ) -> Option { + ) -> Option> { if let Some(def) = sema.resolve_bind_pat_to_const(&ident_pat) { return Some(NameClass::ConstReference(Definition::from(def))); } @@ -638,9 +641,9 @@ impl NameClass { } pub fn classify_lifetime( - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, lifetime: &ast::Lifetime, - ) -> Option { + ) -> Option> { let _p = tracing::info_span!("NameClass::classify_lifetime", ?lifetime).entered(); let parent = lifetime.syntax().parent()?; @@ -723,12 +726,12 @@ impl OperatorClass { /// A model special case is field shorthand syntax, which uses a single /// reference to point to two different defs. #[derive(Debug)] -pub enum NameRefClass { - Definition(Definition, Option), +pub enum NameRefClass<'db> { + Definition(Definition, Option>), FieldShorthand { local_ref: Local, field_ref: Field, - adt_subst: GenericSubstitution, + adt_subst: GenericSubstitution<'db>, }, /// The specific situation where we have an extern crate decl without a rename /// Here we have both a declaration and a reference. @@ -741,13 +744,13 @@ pub enum NameRefClass { }, } -impl NameRefClass { +impl<'db> NameRefClass<'db> { // Note: we don't have unit-tests for this rather important function. // It is primarily exercised via goto definition tests in `ide`. pub fn classify( - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, name_ref: &ast::NameRef, - ) -> Option { + ) -> Option> { let _p = tracing::info_span!("NameRefClass::classify", ?name_ref).entered(); let parent = name_ref.syntax().parent()?; @@ -866,9 +869,9 @@ impl NameRefClass { } pub fn classify_lifetime( - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, lifetime: &ast::Lifetime, - ) -> Option { + ) -> Option> { let _p = tracing::info_span!("NameRefClass::classify_lifetime", ?lifetime).entered(); if lifetime.text() == "'static" { return Some(NameRefClass::Definition( diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs index ac592dfe93cf..9f35988924b9 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs @@ -25,26 +25,26 @@ use crate::{ /// * assists /// * etc. #[derive(Debug)] -pub enum ImportCandidate { +pub enum ImportCandidate<'db> { /// A path, qualified (`std::collections::HashMap`) or not (`HashMap`). Path(PathImportCandidate), /// A trait associated function (with no self parameter) or an associated constant. /// For 'test_mod::TestEnum::test_function', `ty` is the `test_mod::TestEnum` expression type /// and `name` is the `test_function` - TraitAssocItem(TraitImportCandidate), + TraitAssocItem(TraitImportCandidate<'db>), /// A trait method with self parameter. /// For 'test_enum.test_method()', `ty` is the `test_enum` expression type /// and `name` is the `test_method` - TraitMethod(TraitImportCandidate), + TraitMethod(TraitImportCandidate<'db>), } /// A trait import needed for a given associated item access. /// For `some::path::SomeStruct::ASSOC_`, contains the /// type of `some::path::SomeStruct` and `ASSOC_` as the item name. #[derive(Debug)] -pub struct TraitImportCandidate { +pub struct TraitImportCandidate<'db> { /// A type of the item that has the associated item accessed at. - pub receiver_ty: Type, + pub receiver_ty: Type<'db>, /// The associated item name that the trait to import should contain. pub assoc_item_name: NameToImport, } @@ -100,16 +100,16 @@ impl NameToImport { /// A struct to find imports in the project, given a certain name (or its part) and the context. #[derive(Debug)] -pub struct ImportAssets { - import_candidate: ImportCandidate, +pub struct ImportAssets<'db> { + import_candidate: ImportCandidate<'db>, candidate_node: SyntaxNode, module_with_candidate: Module, } -impl ImportAssets { +impl<'db> ImportAssets<'db> { pub fn for_method_call( method_call: &ast::MethodCallExpr, - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, ) -> Option { let candidate_node = method_call.syntax().clone(); Some(Self { @@ -121,7 +121,7 @@ impl ImportAssets { pub fn for_exact_path( fully_qualified_path: &ast::Path, - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, ) -> Option { let candidate_node = fully_qualified_path.syntax().clone(); if let Some(use_tree) = candidate_node.ancestors().find_map(ast::UseTree::cast) { @@ -139,7 +139,7 @@ impl ImportAssets { }) } - pub fn for_ident_pat(sema: &Semantics<'_, RootDatabase>, pat: &ast::IdentPat) -> Option { + pub fn for_ident_pat(sema: &Semantics<'db, RootDatabase>, pat: &ast::IdentPat) -> Option { if !pat.is_simple_ident() { return None; } @@ -156,7 +156,7 @@ impl ImportAssets { module_with_candidate: Module, qualifier: Option, fuzzy_name: String, - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, candidate_node: SyntaxNode, ) -> Option { Some(Self { @@ -168,7 +168,7 @@ impl ImportAssets { pub fn for_fuzzy_method_call( module_with_method_call: Module, - receiver_ty: Type, + receiver_ty: Type<'db>, fuzzy_method_name: String, candidate_node: SyntaxNode, ) -> Option { @@ -229,14 +229,14 @@ impl LocatedImport { } } -impl ImportAssets { - pub fn import_candidate(&self) -> &ImportCandidate { +impl<'db> ImportAssets<'db> { + pub fn import_candidate(&self) -> &ImportCandidate<'db> { &self.import_candidate } pub fn search_for_imports( &self, - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, cfg: ImportPathConfig, prefix_kind: PrefixKind, ) -> impl Iterator { @@ -247,7 +247,7 @@ impl ImportAssets { /// This may return non-absolute paths if a part of the returned path is already imported into scope. pub fn search_for_relative_paths( &self, - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, cfg: ImportPathConfig, ) -> impl Iterator { let _p = tracing::info_span!("ImportAssets::search_for_relative_paths").entered(); @@ -286,7 +286,7 @@ impl ImportAssets { fn search_for( &self, - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, prefixed: Option, cfg: ImportPathConfig, ) -> impl Iterator { @@ -533,11 +533,11 @@ fn item_for_path_search_assoc(db: &RootDatabase, assoc_item: AssocItem) -> Optio }) } -fn trait_applicable_items( - db: &RootDatabase, +fn trait_applicable_items<'db>( + db: &'db RootDatabase, current_crate: Crate, - scope: &SemanticsScope<'_>, - trait_candidate: &TraitImportCandidate, + scope: &SemanticsScope<'db>, + trait_candidate: &TraitImportCandidate<'db>, trait_assoc_item: bool, mod_path: impl Fn(ItemInNs) -> Option, scope_filter: impl Fn(hir::Trait) -> bool, @@ -709,9 +709,9 @@ fn get_mod_path( } } -impl ImportCandidate { +impl<'db> ImportCandidate<'db> { fn for_method_call( - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, method_call: &ast::MethodCallExpr, ) -> Option { match sema.resolve_method_call(method_call) { @@ -725,7 +725,7 @@ impl ImportCandidate { } } - fn for_regular_path(sema: &Semantics<'_, RootDatabase>, path: &ast::Path) -> Option { + fn for_regular_path(sema: &Semantics<'db, RootDatabase>, path: &ast::Path) -> Option { if sema.resolve_path(path).is_some() { return None; } @@ -736,7 +736,7 @@ impl ImportCandidate { ) } - fn for_name(sema: &Semantics<'_, RootDatabase>, name: &ast::Name) -> Option { + fn for_name(sema: &Semantics<'db, RootDatabase>, name: &ast::Name) -> Option { if sema .scope(name.syntax())? .speculative_resolve(&make::ext::ident_path(&name.text())) @@ -753,17 +753,17 @@ impl ImportCandidate { fn for_fuzzy_path( qualifier: Option, fuzzy_name: String, - sema: &Semantics<'_, RootDatabase>, + sema: &Semantics<'db, RootDatabase>, ) -> Option { path_import_candidate(sema, qualifier, NameToImport::fuzzy(fuzzy_name)) } } -fn path_import_candidate( - sema: &Semantics<'_, RootDatabase>, +fn path_import_candidate<'db>( + sema: &Semantics<'db, RootDatabase>, qualifier: Option, name: NameToImport, -) -> Option { +) -> Option> { Some(match qualifier { Some(qualifier) => match sema.resolve_path(&qualifier) { Some(PathResolution::Def(ModuleDef::BuiltinType(_))) | None => { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs index c5ad64ed5941..7d460f72492c 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs @@ -429,7 +429,7 @@ pub struct FindUsages<'a> { /// The container of our definition should it be an assoc item assoc_item_container: Option, /// whether to search for the `Self` type of the definition - include_self_kw_refs: Option, + include_self_kw_refs: Option>, /// whether to search for the `self` module search_self_mod: bool, } @@ -1087,12 +1087,12 @@ impl<'a> FindUsages<'a> { fn found_self_ty_name_ref( &self, - self_ty: &hir::Type, + self_ty: &hir::Type<'_>, name_ref: &ast::NameRef, sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool, ) -> bool { // See https://github.com/rust-lang/rust-analyzer/pull/15864/files/e0276dc5ddc38c65240edb408522bb869f15afb4#r1389848845 - let ty_eq = |ty: hir::Type| match (ty.as_adt(), self_ty.as_adt()) { + let ty_eq = |ty: hir::Type<'_>| match (ty.as_adt(), self_ty.as_adt()) { (Some(ty), Some(self_ty)) => ty == self_ty, (None, None) => ty == *self_ty, _ => false, @@ -1315,7 +1315,7 @@ impl<'a> FindUsages<'a> { } } -fn def_to_ty(sema: &Semantics<'_, RootDatabase>, def: &Definition) -> Option { +fn def_to_ty<'db>(sema: &Semantics<'db, RootDatabase>, def: &Definition) -> Option> { match def { Definition::Adt(adt) => Some(adt.ty(sema.db)), Definition::TypeAlias(it) => Some(it.ty(sema.db)), diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs index 9b9f450bc734..995bf72dca16 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs @@ -151,10 +151,10 @@ impl NameGenerator { /// - If `ty` is an `impl Trait`, it will suggest the name of the first trait. /// /// If the suggested name conflicts with reserved keywords, it will return `None`. - pub fn for_type( + pub fn for_type<'db>( &mut self, - ty: &hir::Type, - db: &RootDatabase, + ty: &hir::Type<'db>, + db: &'db RootDatabase, edition: Edition, ) -> Option { let name = name_of_type(ty, db, edition)?; @@ -373,7 +373,11 @@ fn from_type(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option Option { +fn name_of_type<'db>( + ty: &hir::Type<'db>, + db: &'db RootDatabase, + edition: Edition, +) -> Option { let name = if let Some(adt) = ty.as_adt() { let name = adt.name(db).display(db, edition).to_string(); @@ -407,7 +411,11 @@ fn name_of_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option, db: &RootDatabase, edition: Edition) -> SmolStr { +fn sequence_name<'db>( + inner_ty: Option<&hir::Type<'db>>, + db: &'db RootDatabase, + edition: Edition, +) -> SmolStr { let items_str = SmolStr::new_static("items"); let Some(inner_ty) = inner_ty else { return items_str; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/ty_filter.rs b/src/tools/rust-analyzer/crates/ide-db/src/ty_filter.rs index 63ce0ddbb8fc..095256d8294e 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/ty_filter.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/ty_filter.rs @@ -10,7 +10,7 @@ use syntax::ast::{self, Pat, make}; use crate::RootDatabase; /// Enum types that implement `std::ops::Try` trait. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub enum TryEnum { Result, Option, @@ -20,7 +20,7 @@ impl TryEnum { const ALL: [TryEnum; 2] = [TryEnum::Option, TryEnum::Result]; /// Returns `Some(..)` if the provided type is an enum that implements `std::ops::Try`. - pub fn from_ty(sema: &Semantics<'_, RootDatabase>, ty: &hir::Type) -> Option { + pub fn from_ty(sema: &Semantics<'_, RootDatabase>, ty: &hir::Type<'_>) -> Option { let enum_ = match ty.as_adt() { Some(hir::Adt::Enum(it)) => it, _ => return None, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/use_trivial_constructor.rs b/src/tools/rust-analyzer/crates/ide-db/src/use_trivial_constructor.rs index a4a93e36f0e1..f63cd92694b3 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/use_trivial_constructor.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/use_trivial_constructor.rs @@ -11,7 +11,7 @@ use syntax::{ pub fn use_trivial_constructor( db: &crate::RootDatabase, path: Path, - ty: &hir::Type, + ty: &hir::Type<'_>, edition: Edition, ) -> Option { match ty.as_adt() { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs index 7d2ac373dc08..afd1687ae073 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs @@ -7,7 +7,7 @@ use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; // This diagnostic is triggered if a call is made on something that is not callable. pub(crate) fn expected_function( ctx: &DiagnosticsContext<'_>, - d: &hir::ExpectedFunction, + d: &hir::ExpectedFunction<'_>, ) -> Diagnostic { Diagnostic::new_with_syntax_node_ptr( ctx, diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs index 7a6e98fe1b54..a59077b757b1 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs @@ -18,7 +18,7 @@ macro_rules! format_ty { // Diagnostic: invalid-cast // // This diagnostic is triggered if the code contains an illegal cast -pub(crate) fn invalid_cast(ctx: &DiagnosticsContext<'_>, d: &hir::InvalidCast) -> Diagnostic { +pub(crate) fn invalid_cast(ctx: &DiagnosticsContext<'_>, d: &hir::InvalidCast<'_>) -> Diagnostic { let display_range = ctx.sema.diagnostics_display_range(d.expr.map(|it| it.into())); let (code, message) = match d.error { CastError::CastToBool => ( @@ -106,7 +106,10 @@ pub(crate) fn invalid_cast(ctx: &DiagnosticsContext<'_>, d: &hir::InvalidCast) - // Diagnostic: cast-to-unsized // // This diagnostic is triggered when casting to an unsized type -pub(crate) fn cast_to_unsized(ctx: &DiagnosticsContext<'_>, d: &hir::CastToUnsized) -> Diagnostic { +pub(crate) fn cast_to_unsized( + ctx: &DiagnosticsContext<'_>, + d: &hir::CastToUnsized<'_>, +) -> Diagnostic { let display_range = ctx.sema.diagnostics_display_range(d.expr.map(|it| it.into())); Diagnostic::new( DiagnosticCode::RustcHardError("E0620"), diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs index 2b76efb1965b..8a5d82b48c01 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -106,7 +106,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option| match ctx.config.expr_fill_default { ExprFillDefaultMode::Todo => make::ext::expr_todo(), ExprFillDefaultMode::Underscore => make::ext::expr_underscore(), ExprFillDefaultMode::Default => { @@ -180,7 +180,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option, db: &dyn HirDatabase, module: hir::Module, edition: Edition, @@ -198,7 +198,7 @@ fn make_ty( fn get_default_constructor( ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields, - ty: &Type, + ty: &Type<'_>, ) -> Option { if let Some(builtin_ty) = ty.as_builtin() { if builtin_ty.is_int() || builtin_ty.is_uint() { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs index 6bd5417b25d7..d8f6e813d800 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs @@ -628,6 +628,17 @@ fn main() { #[test] fn orphan_unsafe_format_args() { // Checks that we don't place orphan arguments for formatting under an unsafe block. + check_diagnostics( + r#" +//- minicore: fmt_before_1_89_0 +fn foo() { + let p = 0xDEADBEEF as *const i32; + format_args!("", *p); + // ^^ error: dereference of raw pointer is unsafe and requires an unsafe function or block +} + "#, + ); + check_diagnostics( r#" //- minicore: fmt @@ -958,4 +969,18 @@ impl FooTrait for S2 { "#, ); } + + #[test] + fn no_false_positive_on_format_args_since_1_89_0() { + check_diagnostics( + r#" +//- minicore: fmt +fn test() { + let foo = 10; + let bar = true; + let _x = format_args!("{} {0} {} {last}", foo, bar, last = "!"); +} + "#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs index 01cf5e8fa522..0928262d22fa 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs @@ -4,7 +4,10 @@ use hir::HirDisplay; // Diagnostic: moved-out-of-ref // // This diagnostic is triggered on moving non copy things out of references. -pub(crate) fn moved_out_of_ref(ctx: &DiagnosticsContext<'_>, d: &hir::MovedOutOfRef) -> Diagnostic { +pub(crate) fn moved_out_of_ref( + ctx: &DiagnosticsContext<'_>, + d: &hir::MovedOutOfRef<'_>, +) -> Diagnostic { Diagnostic::new_with_syntax_node_ptr( ctx, DiagnosticCode::RustcHardError("E0507"), @@ -217,4 +220,23 @@ fn test() { "#, ) } + + #[test] + fn regression_18201() { + check_diagnostics( + r#" +//- minicore: copy +struct NotCopy; +struct S(NotCopy); +impl S { + fn f(&mut self) { + || { + if let ref mut _cb = self.0 { + } + }; + } +} +"#, + ) + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs index ef42f2dc7448..0edab5e0b3b1 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs @@ -1,5 +1,4 @@ use either::Either; -use hir::{Field, HasCrate}; use hir::{HasSource, HirDisplay, Semantics, VariantId, db::ExpandDatabase}; use ide_db::text_edit::TextEdit; use ide_db::{EditionedFileId, RootDatabase, source_change::SourceChange}; @@ -8,7 +7,10 @@ use syntax::{ ast::{self, edit::IndentLevel, make}, }; -use crate::{Assist, Diagnostic, DiagnosticCode, DiagnosticsContext, fix}; +use crate::{ + Assist, Diagnostic, DiagnosticCode, DiagnosticsContext, fix, + handlers::private_field::field_is_private_fixes, +}; // Diagnostic: no-such-field // @@ -37,8 +39,8 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) -> Option, d: &hir::NoSuchField) -> Option, - usage_file_id: EditionedFileId, - record_expr_field: &ast::RecordExprField, - private_field: Field, -) -> Option> { - let def_crate = private_field.krate(sema.db); - let usage_crate = sema.file_to_module_def(usage_file_id.file_id(sema.db))?.krate(); - let visibility = if usage_crate == def_crate { "pub(crate) " } else { "pub " }; - - let source = private_field.source(sema.db)?; - let (range, _) = source.syntax().original_file_range_opt(sema.db)?; - let source_change = SourceChange::from_text_edit( - range.file_id.file_id(sema.db), - TextEdit::insert(range.range.start(), visibility.into()), - ); - - Some(vec![fix( - "increase_field_visibility", - "Increase field visibility", - source_change, - sema.original_range(record_expr_field.syntax()).range, - )]) -} - fn missing_record_expr_field_fixes( sema: &Semantics<'_, RootDatabase>, usage_file_id: EditionedFileId, diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_field.rs index 5b4273a5a627..69cd0d27cb06 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_field.rs @@ -1,4 +1,8 @@ -use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; +use hir::{EditionedFileId, FileRange, HasCrate, HasSource, Semantics}; +use ide_db::{RootDatabase, assists::Assist, source_change::SourceChange, text_edit::TextEdit}; +use syntax::{AstNode, TextRange, TextSize, ast::HasVisibility}; + +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, fix}; // Diagnostic: private-field // @@ -16,11 +20,59 @@ pub(crate) fn private_field(ctx: &DiagnosticsContext<'_>, d: &hir::PrivateField) d.expr.map(|it| it.into()), ) .stable() + .with_fixes(field_is_private_fixes( + &ctx.sema, + d.expr.file_id.original_file(ctx.sema.db), + d.field, + ctx.sema.original_range(d.expr.to_node(ctx.sema.db).syntax()).range, + )) +} + +pub(crate) fn field_is_private_fixes( + sema: &Semantics<'_, RootDatabase>, + usage_file_id: EditionedFileId, + private_field: hir::Field, + fix_range: TextRange, +) -> Option> { + let def_crate = private_field.krate(sema.db); + let usage_crate = sema.file_to_module_def(usage_file_id.file_id(sema.db))?.krate(); + let mut visibility_text = if usage_crate == def_crate { "pub(crate) " } else { "pub " }; + + let source = private_field.source(sema.db)?; + let existing_visibility = match &source.value { + hir::FieldSource::Named(it) => it.visibility(), + hir::FieldSource::Pos(it) => it.visibility(), + }; + let range = match existing_visibility { + Some(visibility) => { + // If there is an existing visibility, don't insert whitespace after. + visibility_text = visibility_text.trim_end(); + source.with_value(visibility.syntax()).original_file_range_opt(sema.db)?.0 + } + None => { + let (range, _) = source.syntax().original_file_range_opt(sema.db)?; + FileRange { + file_id: range.file_id, + range: TextRange::at(range.range.start(), TextSize::new(0)), + } + } + }; + let source_change = SourceChange::from_text_edit( + range.file_id.file_id(sema.db), + TextEdit::replace(range.range, visibility_text.into()), + ); + + Some(vec![fix( + "increase_field_visibility", + "Increase field visibility", + source_change, + fix_range, + )]) } #[cfg(test)] mod tests { - use crate::tests::check_diagnostics; + use crate::tests::{check_diagnostics, check_fix}; #[test] fn private_field() { @@ -29,7 +81,7 @@ mod tests { mod module { pub struct Struct { field: u32 } } fn main(s: module::Struct) { s.field; - //^^^^^^^ error: field `field` of `Struct` is private + //^^^^^^^ 💡 error: field `field` of `Struct` is private } "#, ); @@ -42,7 +94,7 @@ fn main(s: module::Struct) { mod module { pub struct Struct(u32); } fn main(s: module::Struct) { s.0; - //^^^ error: field `0` of `Struct` is private + //^^^ 💡 error: field `0` of `Struct` is private } "#, ); @@ -113,4 +165,68 @@ fn main() { "#, ); } + + #[test] + fn change_visibility_fix() { + check_fix( + r#" +pub mod foo { + pub mod bar { + pub struct Struct { + field: i32, + } + } +} + +fn foo(v: foo::bar::Struct) { + v.field$0; +} + "#, + r#" +pub mod foo { + pub mod bar { + pub struct Struct { + pub(crate) field: i32, + } + } +} + +fn foo(v: foo::bar::Struct) { + v.field; +} + "#, + ); + } + + #[test] + fn change_visibility_with_existing_visibility() { + check_fix( + r#" +pub mod foo { + pub mod bar { + pub struct Struct { + pub(super) field: i32, + } + } +} + +fn foo(v: foo::bar::Struct) { + v.field$0; +} + "#, + r#" +pub mod foo { + pub mod bar { + pub struct Struct { + pub(crate) field: i32, + } + } +} + +fn foo(v: foo::bar::Struct) { + v.field; +} + "#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 076df1ab0f82..e2957fcaefb4 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -20,7 +20,7 @@ use crate::{Assist, Diagnostic, DiagnosticCode, DiagnosticsContext, adjusted_dis // // This diagnostic is triggered when the type of an expression or pattern does not match // the expected type. -pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Diagnostic { +pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch<'_>) -> Diagnostic { let display_range = adjusted_display_range(ctx, d.expr_or_pat, &|node| { let Either::Left(expr) = node else { return None }; let salient_token_range = match expr { @@ -39,7 +39,7 @@ pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) cov_mark::hit!(type_mismatch_range_adjustment); Some(salient_token_range) }); - let mut diag = Diagnostic::new( + Diagnostic::new( DiagnosticCode::RustcHardError("E0308"), format!( "expected {}, found {}", @@ -52,14 +52,10 @@ pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) ), display_range, ) - .with_fixes(fixes(ctx, d)); - if diag.fixes.is_some() { - diag.experimental = false; - } - diag + .with_fixes(fixes(ctx, d)) } -fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Option> { +fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch<'_>) -> Option> { let mut fixes = Vec::new(); if let Some(expr_ptr) = d.expr_or_pat.value.cast::() { @@ -76,7 +72,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Option, - d: &hir::TypeMismatch, + d: &hir::TypeMismatch<'_>, expr_ptr: &InFile>, acc: &mut Vec, ) -> Option<()> { @@ -98,7 +94,7 @@ fn add_reference( fn add_missing_ok_or_some( ctx: &DiagnosticsContext<'_>, - d: &hir::TypeMismatch, + d: &hir::TypeMismatch<'_>, expr_ptr: &InFile>, acc: &mut Vec, ) -> Option<()> { @@ -188,7 +184,7 @@ fn add_missing_ok_or_some( fn remove_unnecessary_wrapper( ctx: &DiagnosticsContext<'_>, - d: &hir::TypeMismatch, + d: &hir::TypeMismatch<'_>, expr_ptr: &InFile>, acc: &mut Vec, ) -> Option<()> { @@ -271,7 +267,7 @@ fn remove_unnecessary_wrapper( fn remove_semicolon( ctx: &DiagnosticsContext<'_>, - d: &hir::TypeMismatch, + d: &hir::TypeMismatch<'_>, expr_ptr: &InFile>, acc: &mut Vec, ) -> Option<()> { @@ -301,7 +297,7 @@ fn remove_semicolon( fn str_ref_to_owned( ctx: &DiagnosticsContext<'_>, - d: &hir::TypeMismatch, + d: &hir::TypeMismatch<'_>, expr_ptr: &InFile>, acc: &mut Vec, ) -> Option<()> { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs index 1915a88dd002..8d4277026905 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs @@ -20,7 +20,7 @@ use syntax::AstNode; // Diagnostic: typed-hole // // This diagnostic is triggered when an underscore expression is used in an invalid position. -pub(crate) fn typed_hole(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Diagnostic { +pub(crate) fn typed_hole(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole<'_>) -> Diagnostic { let display_range = ctx.sema.diagnostics_display_range(d.expr.map(|it| it.into())); let (message, fixes) = if d.expected.is_unknown() { ("`_` expressions may only appear on the left-hand side of an assignment".to_owned(), None) @@ -41,7 +41,7 @@ pub(crate) fn typed_hole(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Di .with_fixes(fixes) } -fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option> { +fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole<'_>) -> Option> { let db = ctx.sema.db; let root = db.parse_or_expand(d.expr.file_id); let (original_range, _) = @@ -61,7 +61,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option }; let paths = term_search(&term_search_ctx); - let mut formatter = |_: &hir::Type| String::from("_"); + let mut formatter = |_: &hir::Type<'_>| String::from("_"); let assists: Vec = d .expected diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs index 0649c97f8205..690158989679 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs @@ -25,7 +25,7 @@ use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, adjusted_display_ran // This diagnostic is triggered if a field does not exist on a given type. pub(crate) fn unresolved_field( ctx: &DiagnosticsContext<'_>, - d: &hir::UnresolvedField, + d: &hir::UnresolvedField<'_>, ) -> Diagnostic { let method_suffix = if d.method_with_same_name_exists { ", but a method with a similar name exists" @@ -54,7 +54,7 @@ pub(crate) fn unresolved_field( .with_fixes(fixes(ctx, d)) } -fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option> { +fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField<'_>) -> Option> { let mut fixes = Vec::new(); if d.method_with_same_name_exists { fixes.extend(method_fix(ctx, &d.expr)); @@ -64,7 +64,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option, d: &hir::UnresolvedField) -> Option { +fn field_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField<'_>) -> Option { // Get the FileRange of the invalid field access let root = ctx.sema.db.parse_or_expand(d.expr.file_id); let expr = d.expr.value.to_node(&root).left()?; diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs index 00c2a8c4c468..1f2d671249de 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs @@ -18,7 +18,7 @@ use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, adjusted_display_ran // This diagnostic is triggered if a method does not exist on a given type. pub(crate) fn unresolved_method( ctx: &DiagnosticsContext<'_>, - d: &hir::UnresolvedMethodCall, + d: &hir::UnresolvedMethodCall<'_>, ) -> Diagnostic { let suffix = if d.field_with_same_name.is_some() { ", but a field with a similar name exists" @@ -49,7 +49,7 @@ pub(crate) fn unresolved_method( .with_fixes(fixes(ctx, d)) } -fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -> Option> { +fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall<'_>) -> Option> { let field_fix = if let Some(ty) = &d.field_with_same_name { field_fix(ctx, d, ty) } else { @@ -72,8 +72,8 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -> Option< fn field_fix( ctx: &DiagnosticsContext<'_>, - d: &hir::UnresolvedMethodCall, - ty: &hir::Type, + d: &hir::UnresolvedMethodCall<'_>, + ty: &hir::Type<'_>, ) -> Option { if !ty.impls_fnonce(ctx.sema.db) { return None; @@ -107,7 +107,10 @@ fn field_fix( }) } -fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -> Option { +fn assoc_func_fix( + ctx: &DiagnosticsContext<'_>, + d: &hir::UnresolvedMethodCall<'_>, +) -> Option { if let Some(f) = d.assoc_func_with_same_name { let db = ctx.sema.db; diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs index 43c56ac8bec5..e4b20f3f1aad 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs @@ -110,7 +110,7 @@ pub struct SsrMatches { pub struct MatchFinder<'db> { /// Our source of information about the user's code. sema: Semantics<'db, ide_db::RootDatabase>, - rules: Vec, + rules: Vec>, resolution_scope: resolving::ResolutionScope<'db>, restrict_ranges: Vec, } diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs index cff4eede0426..b350315ba548 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs @@ -84,12 +84,12 @@ pub(crate) struct MatchFailed { /// Checks if `code` matches the search pattern found in `search_scope`, returning information about /// the match, if it does. Since we only do matching in this module and searching is done by the /// parent module, we don't populate nested matches. -pub(crate) fn get_match( +pub(crate) fn get_match<'db>( debug_active: bool, - rule: &ResolvedRule, + rule: &ResolvedRule<'db>, code: &SyntaxNode, restrict_range: &Option, - sema: &Semantics<'_, ide_db::RootDatabase>, + sema: &Semantics<'db, ide_db::RootDatabase>, ) -> Result { record_match_fails_reasons_scope(debug_active, || { Matcher::try_match(rule, code, restrict_range, sema) @@ -102,7 +102,7 @@ struct Matcher<'db, 'sema> { /// If any placeholders come from anywhere outside of this range, then the match will be /// rejected. restrict_range: Option, - rule: &'sema ResolvedRule, + rule: &'sema ResolvedRule<'db>, } /// Which phase of matching we're currently performing. We do two phases because most attempted @@ -117,7 +117,7 @@ enum Phase<'a> { impl<'db, 'sema> Matcher<'db, 'sema> { fn try_match( - rule: &ResolvedRule, + rule: &ResolvedRule<'db>, code: &SyntaxNode, restrict_range: &Option, sema: &'sema Semantics<'db, ide_db::RootDatabase>, @@ -535,7 +535,7 @@ impl<'db, 'sema> Matcher<'db, 'sema> { fn attempt_match_ufcs_to_method_call( &self, phase: &mut Phase<'_>, - pattern_ufcs: &UfcsCallInfo, + pattern_ufcs: &UfcsCallInfo<'db>, code: &ast::MethodCallExpr, ) -> Result<(), MatchFailed> { use ast::HasArgList; @@ -597,7 +597,7 @@ impl<'db, 'sema> Matcher<'db, 'sema> { fn attempt_match_ufcs_to_ufcs( &self, phase: &mut Phase<'_>, - pattern_ufcs: &UfcsCallInfo, + pattern_ufcs: &UfcsCallInfo<'db>, code: &ast::CallExpr, ) -> Result<(), MatchFailed> { use ast::HasArgList; @@ -615,7 +615,7 @@ impl<'db, 'sema> Matcher<'db, 'sema> { /// times. Returns the number of times it needed to be dereferenced. fn check_expr_type( &self, - pattern_type: &hir::Type, + pattern_type: &hir::Type<'db>, expr: &ast::Expr, ) -> Result { use hir::HirDisplay; @@ -656,10 +656,10 @@ impl<'db, 'sema> Matcher<'db, 'sema> { } impl Match { - fn render_template_paths( + fn render_template_paths<'db>( &mut self, - template: &ResolvedPattern, - sema: &Semantics<'_, ide_db::RootDatabase>, + template: &ResolvedPattern<'db>, + sema: &Semantics<'db, ide_db::RootDatabase>, ) -> Result<(), MatchFailed> { let module = sema .scope(&self.matched_node) diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/replacing.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/replacing.rs index 3c92697926f3..752edd6535a6 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/replacing.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/replacing.rs @@ -14,21 +14,21 @@ use crate::{Match, SsrMatches, fragments, resolving::ResolvedRule}; /// Returns a text edit that will replace each match in `matches` with its corresponding replacement /// template. Placeholders in the template will have been substituted with whatever they matched to /// in the original code. -pub(crate) fn matches_to_edit( - db: &dyn hir::db::ExpandDatabase, +pub(crate) fn matches_to_edit<'db>( + db: &'db dyn hir::db::ExpandDatabase, matches: &SsrMatches, file_src: &str, - rules: &[ResolvedRule], + rules: &[ResolvedRule<'db>], ) -> TextEdit { matches_to_edit_at_offset(db, matches, file_src, 0.into(), rules) } -fn matches_to_edit_at_offset( - db: &dyn hir::db::ExpandDatabase, +fn matches_to_edit_at_offset<'db>( + db: &'db dyn hir::db::ExpandDatabase, matches: &SsrMatches, file_src: &str, relative_start: TextSize, - rules: &[ResolvedRule], + rules: &[ResolvedRule<'db>], ) -> TextEdit { let mut edit_builder = TextEdit::builder(); for m in &matches.matches { @@ -40,12 +40,12 @@ fn matches_to_edit_at_offset( edit_builder.finish() } -struct ReplacementRenderer<'a> { - db: &'a dyn hir::db::ExpandDatabase, +struct ReplacementRenderer<'a, 'db> { + db: &'db dyn hir::db::ExpandDatabase, match_info: &'a Match, file_src: &'a str, - rules: &'a [ResolvedRule], - rule: &'a ResolvedRule, + rules: &'a [ResolvedRule<'db>], + rule: &'a ResolvedRule<'db>, out: String, // Map from a range within `out` to a token in `template` that represents a placeholder. This is // used to validate that the generated source code doesn't split any placeholder expansions (see @@ -58,11 +58,11 @@ struct ReplacementRenderer<'a> { edition: Edition, } -fn render_replace( - db: &dyn hir::db::ExpandDatabase, +fn render_replace<'db>( + db: &'db dyn hir::db::ExpandDatabase, match_info: &Match, file_src: &str, - rules: &[ResolvedRule], + rules: &[ResolvedRule<'db>], edition: Edition, ) -> String { let rule = &rules[match_info.rule_index]; @@ -89,7 +89,7 @@ fn render_replace( renderer.out } -impl ReplacementRenderer<'_> { +impl<'db> ReplacementRenderer<'_, 'db> { fn render_node_children(&mut self, node: &SyntaxNode) { for node_or_token in node.children_with_tokens() { self.render_node_or_token(&node_or_token); diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/resolving.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/resolving.rs index a687db4bf58d..8f28a1cd3a62 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/resolving.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/resolving.rs @@ -15,18 +15,18 @@ pub(crate) struct ResolutionScope<'db> { node: SyntaxNode, } -pub(crate) struct ResolvedRule { - pub(crate) pattern: ResolvedPattern, - pub(crate) template: Option, +pub(crate) struct ResolvedRule<'db> { + pub(crate) pattern: ResolvedPattern<'db>, + pub(crate) template: Option>, pub(crate) index: usize, } -pub(crate) struct ResolvedPattern { +pub(crate) struct ResolvedPattern<'db> { pub(crate) placeholders_by_stand_in: FxHashMap, pub(crate) node: SyntaxNode, // Paths in `node` that we've resolved. pub(crate) resolved_paths: FxHashMap, - pub(crate) ufcs_function_calls: FxHashMap, + pub(crate) ufcs_function_calls: FxHashMap>, pub(crate) contains_self: bool, } @@ -36,18 +36,18 @@ pub(crate) struct ResolvedPath { pub(crate) depth: u32, } -pub(crate) struct UfcsCallInfo { +pub(crate) struct UfcsCallInfo<'db> { pub(crate) call_expr: ast::CallExpr, pub(crate) function: hir::Function, - pub(crate) qualifier_type: Option, + pub(crate) qualifier_type: Option>, } -impl ResolvedRule { +impl<'db> ResolvedRule<'db> { pub(crate) fn new( rule: parsing::ParsedRule, - resolution_scope: &ResolutionScope<'_>, + resolution_scope: &ResolutionScope<'db>, index: usize, - ) -> Result { + ) -> Result, SsrError> { let resolver = Resolver { resolution_scope, placeholders_by_stand_in: rule.placeholders_by_stand_in }; let resolved_template = match rule.template { @@ -74,8 +74,8 @@ struct Resolver<'a, 'db> { placeholders_by_stand_in: FxHashMap, } -impl Resolver<'_, '_> { - fn resolve_pattern_tree(&self, pattern: SyntaxNode) -> Result { +impl<'db> Resolver<'_, 'db> { + fn resolve_pattern_tree(&self, pattern: SyntaxNode) -> Result, SsrError> { use syntax::ast::AstNode; use syntax::{SyntaxElement, T}; let mut resolved_paths = FxHashMap::default(); @@ -250,7 +250,7 @@ impl<'db> ResolutionScope<'db> { } } - fn qualifier_type(&self, path: &SyntaxNode) -> Option { + fn qualifier_type(&self, path: &SyntaxNode) -> Option> { use syntax::ast::AstNode; if let Some(path) = ast::Path::cast(path.clone()) { if let Some(qualifier) = path.qualifier() { diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs index 9afbedbb1ab4..99a98fb2a713 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs @@ -21,13 +21,13 @@ pub(crate) struct UsageCache { usages: Vec<(Definition, UsageSearchResult)>, } -impl MatchFinder<'_> { +impl<'db> MatchFinder<'db> { /// Adds all matches for `rule` to `matches_out`. Matches may overlap in ways that make /// replacement impossible, so further processing is required in order to properly nest matches /// and remove overlapping matches. This is done in the `nesting` module. pub(crate) fn find_matches_for_rule( &self, - rule: &ResolvedRule, + rule: &ResolvedRule<'db>, usage_cache: &mut UsageCache, matches_out: &mut Vec, ) { @@ -49,8 +49,8 @@ impl MatchFinder<'_> { fn find_matches_for_pattern_tree( &self, - rule: &ResolvedRule, - pattern: &ResolvedPattern, + rule: &ResolvedRule<'db>, + pattern: &ResolvedPattern<'db>, usage_cache: &mut UsageCache, matches_out: &mut Vec, ) { @@ -144,7 +144,7 @@ impl MatchFinder<'_> { SearchScope::files(&files) } - fn slow_scan(&self, rule: &ResolvedRule, matches_out: &mut Vec) { + fn slow_scan(&self, rule: &ResolvedRule<'db>, matches_out: &mut Vec) { self.search_files_do(|file_id| { let file = self.sema.parse_guess_edition(file_id); let code = file.syntax(); @@ -177,7 +177,7 @@ impl MatchFinder<'_> { fn slow_scan_node( &self, code: &SyntaxNode, - rule: &ResolvedRule, + rule: &ResolvedRule<'db>, restrict_range: &Option, matches_out: &mut Vec, ) { @@ -206,7 +206,7 @@ impl MatchFinder<'_> { fn try_add_match( &self, - rule: &ResolvedRule, + rule: &ResolvedRule<'db>, code: &SyntaxNode, restrict_range: &Option, matches_out: &mut Vec, @@ -274,7 +274,7 @@ impl UsageCache { /// Returns a path that's suitable for path resolution. We exclude builtin types, since they aren't /// something that we can find references to. We then somewhat arbitrarily pick the path that is the /// longest as this is hopefully more likely to be less common, making it faster to find. -fn pick_path_for_usages(pattern: &ResolvedPattern) -> Option<&ResolvedPath> { +fn pick_path_for_usages<'a>(pattern: &'a ResolvedPattern<'_>) -> Option<&'a ResolvedPath> { // FIXME: Take the scope of the resolved path into account. e.g. if there are any paths that are // private to the current module, then we definitely would want to pick them over say a path // from std. Possibly we should go further than this and intersect the search scopes for all diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs index 1bc28f28b6f5..02d96a647328 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs @@ -83,7 +83,7 @@ pub(crate) fn goto_implementation( Some(RangeInfo { range, info: navs }) } -fn impls_for_ty(sema: &Semantics<'_, RootDatabase>, ty: hir::Type) -> Vec { +fn impls_for_ty(sema: &Semantics<'_, RootDatabase>, ty: hir::Type<'_>) -> Vec { Impl::all_for_type(sema.db, ty) .into_iter() .filter_map(|imp| imp.try_to_nav(sema.db)) diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs index 9781e7116dec..86d72fefe05e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs @@ -38,7 +38,7 @@ pub(crate) fn goto_type_definition( } } }; - let mut process_ty = |ty: hir::Type| { + let mut process_ty = |ty: hir::Type<'_>| { // collect from each `ty` into the `res` result vec let ty = ty.strip_references(); ty.walk(db, |t| { diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 5404a9dc2cec..e4d6279759ed 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -426,7 +426,7 @@ pub(crate) fn hover_for_definition( sema: &Semantics<'_, RootDatabase>, file_id: FileId, def: Definition, - subst: Option, + subst: Option>, scope_node: &SyntaxNode, macro_arm: Option, render_extras: bool, @@ -483,10 +483,10 @@ pub(crate) fn hover_for_definition( } } -fn notable_traits( - db: &RootDatabase, - ty: &hir::Type, -) -> Vec<(hir::Trait, Vec<(Option, hir::Name)>)> { +fn notable_traits<'db>( + db: &'db RootDatabase, + ty: &hir::Type<'db>, +) -> Vec<(hir::Trait, Vec<(Option>, hir::Name)>)> { db.notable_traits_in_deps(ty.krate(db).into()) .iter() .flat_map(|it| &**it) @@ -567,8 +567,8 @@ fn runnable_action( fn goto_type_action_for_def( db: &RootDatabase, def: Definition, - notable_traits: &[(hir::Trait, Vec<(Option, hir::Name)>)], - subst_types: Option>, + notable_traits: &[(hir::Trait, Vec<(Option>, hir::Name)>)], + subst_types: Option)>>, edition: Edition, ) -> Option { let mut targets: Vec = Vec::new(); @@ -622,7 +622,7 @@ fn goto_type_action_for_def( fn walk_and_push_ty( db: &RootDatabase, - ty: &hir::Type, + ty: &hir::Type<'_>, push_new_def: &mut dyn FnMut(hir::ModuleDef), ) { ty.walk(db, |t| { diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index c24864a18bdf..670210d4998d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -476,10 +476,10 @@ pub(super) fn definition( db: &RootDatabase, def: Definition, famous_defs: Option<&FamousDefs<'_, '_>>, - notable_traits: &[(Trait, Vec<(Option, Name)>)], + notable_traits: &[(Trait, Vec<(Option>, Name)>)], macro_arm: Option, render_extras: bool, - subst_types: Option<&Vec<(Symbol, Type)>>, + subst_types: Option<&Vec<(Symbol, Type<'_>)>>, config: &HoverConfig, edition: Edition, display_target: DisplayTarget, @@ -938,7 +938,7 @@ pub(super) fn literal( fn render_notable_trait( db: &RootDatabase, - notable_traits: &[(Trait, Vec<(Option, Name)>)], + notable_traits: &[(Trait, Vec<(Option>, Name)>)], edition: Edition, display_target: DisplayTarget, ) -> Option { @@ -979,7 +979,7 @@ fn render_notable_trait( fn type_info( sema: &Semantics<'_, RootDatabase>, config: &HoverConfig, - ty: TypeInfo, + ty: TypeInfo<'_>, edition: Edition, display_target: DisplayTarget, ) -> Option { @@ -1038,7 +1038,7 @@ fn type_info( fn closure_ty( sema: &Semantics<'_, RootDatabase>, config: &HoverConfig, - TypeInfo { original, adjusted }: &TypeInfo, + TypeInfo { original, adjusted }: &TypeInfo<'_>, edition: Edition, display_target: DisplayTarget, ) -> Option { diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs index b094b098462f..19e5509681aa 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs @@ -722,14 +722,14 @@ impl InlayHintLabelBuilder<'_> { fn label_of_ty( famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, - ty: &hir::Type, + ty: &hir::Type<'_>, display_target: DisplayTarget, ) -> Option { fn rec( sema: &Semantics<'_, RootDatabase>, famous_defs: &FamousDefs<'_, '_>, mut max_length: Option, - ty: &hir::Type, + ty: &hir::Type<'_>, label_builder: &mut InlayHintLabelBuilder<'_>, config: &InlayHintsConfig, display_target: DisplayTarget, @@ -788,11 +788,11 @@ fn label_of_ty( } /// Checks if the type is an Iterator from std::iter and returns the iterator trait and the item type of the concrete iterator. -fn hint_iterator( - sema: &Semantics<'_, RootDatabase>, - famous_defs: &FamousDefs<'_, '_>, - ty: &hir::Type, -) -> Option<(hir::Trait, hir::TypeAlias, hir::Type)> { +fn hint_iterator<'db>( + sema: &Semantics<'db, RootDatabase>, + famous_defs: &FamousDefs<'_, 'db>, + ty: &hir::Type<'db>, +) -> Option<(hir::Trait, hir::TypeAlias, hir::Type<'db>)> { let db = sema.db; let strukt = ty.strip_references().as_adt()?; let krate = strukt.module(db).krate(); @@ -826,7 +826,7 @@ fn ty_to_text_edit( sema: &Semantics<'_, RootDatabase>, config: &InlayHintsConfig, node_for_hint: &SyntaxNode, - ty: &hir::Type, + ty: &hir::Type<'_>, offset_to_insert_ty: TextSize, additional_edits: &dyn Fn(&mut TextEditBuilder), prefix: impl Into, diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs index 5ff9fee60abf..5174228466c0 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs @@ -87,10 +87,10 @@ pub(super) fn hints( Some(()) } -fn get_callable( - sema: &Semantics<'_, RootDatabase>, +fn get_callable<'db>( + sema: &Semantics<'db, RootDatabase>, expr: &ast::Expr, -) -> Option<(hir::Callable, ast::ArgList)> { +) -> Option<(hir::Callable<'db>, ast::ArgList)> { match expr { ast::Expr::CallExpr(expr) => { let descended = sema.descend_node_into_attributes(expr.clone()).pop(); diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index 82dbcde4c06f..b3b8deb61fc0 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -409,7 +409,7 @@ impl Analysis { self.with_db(|db| typing::on_enter(db, position)) } - pub const SUPPORTED_TRIGGER_CHARS: &'static str = typing::TRIGGER_CHARS; + pub const SUPPORTED_TRIGGER_CHARS: &[char] = typing::TRIGGER_CHARS; /// Returns an edit which should be applied after a character was typed. /// @@ -421,7 +421,7 @@ impl Analysis { char_typed: char, ) -> Cancellable> { // Fast path to not even parse the file. - if !typing::TRIGGER_CHARS.contains(char_typed) { + if !typing::TRIGGER_CHARS.contains(&char_typed) { return Ok(None); } diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs index 0e17b3559074..e30a3ebefb98 100644 --- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs +++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs @@ -278,7 +278,7 @@ fn signature_help_for_call( } res.signature.push(')'); - let mut render = |ret_type: hir::Type| { + let mut render = |ret_type: hir::Type<'_>| { if !ret_type.is_unit() { format_to!(res.signature, " -> {}", ret_type.display(db, display_target)); } @@ -597,11 +597,11 @@ fn signature_help_for_tuple_expr( Some(res) } -fn signature_help_for_record_( - sema: &Semantics<'_, RootDatabase>, +fn signature_help_for_record_<'db>( + sema: &Semantics<'db, RootDatabase>, field_list_children: SyntaxElementChildren, path: &ast::Path, - fields2: impl Iterator, + fields2: impl Iterator)>, token: SyntaxToken, edition: Edition, display_target: DisplayTarget, @@ -689,13 +689,13 @@ fn signature_help_for_record_( Some(res) } -fn signature_help_for_tuple_pat_ish( - db: &RootDatabase, +fn signature_help_for_tuple_pat_ish<'db>( + db: &'db RootDatabase, mut res: SignatureHelp, pat: &SyntaxNode, token: SyntaxToken, mut field_pats: AstChildren, - fields: impl ExactSizeIterator, + fields: impl ExactSizeIterator>, display_target: DisplayTarget, ) -> SignatureHelp { let rest_pat = field_pats.find(|it| matches!(it, ast::Pat::RestPat(_))); diff --git a/src/tools/rust-analyzer/crates/ide/src/typing.rs b/src/tools/rust-analyzer/crates/ide/src/typing.rs index 4df7e25223d9..ed55ac5bf04b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/typing.rs +++ b/src/tools/rust-analyzer/crates/ide/src/typing.rs @@ -15,6 +15,7 @@ mod on_enter; +use either::Either; use hir::EditionedFileId; use ide_db::{FilePosition, RootDatabase, base_db::RootQueryDb}; use span::Edition; @@ -33,7 +34,7 @@ use crate::SourceChange; pub(crate) use on_enter::on_enter; // Don't forget to add new trigger characters to `server_capabilities` in `caps.rs`. -pub(crate) const TRIGGER_CHARS: &str = ".=<>{(|"; +pub(crate) const TRIGGER_CHARS: &[char] = &['.', '=', '<', '>', '{', '(', '|', '+']; struct ExtendedTextEdit { edit: TextEdit, @@ -66,7 +67,7 @@ pub(crate) fn on_char_typed( position: FilePosition, char_typed: char, ) -> Option { - if !stdx::always!(TRIGGER_CHARS.contains(char_typed)) { + if !TRIGGER_CHARS.contains(&char_typed) { return None; } // FIXME: We need to figure out the edition of the file here, but that means hitting the @@ -101,6 +102,7 @@ fn on_char_typed_( '>' => on_right_angle_typed(&file.tree(), offset), '{' | '(' | '<' => on_opening_delimiter_typed(file, offset, char_typed, edition), '|' => on_pipe_typed(&file.tree(), offset), + '+' => on_plus_typed(&file.tree(), offset), _ => None, } .map(conv) @@ -402,6 +404,28 @@ fn on_pipe_typed(file: &SourceFile, offset: TextSize) -> Option { Some(TextEdit::insert(after_lpipe, "|".to_owned())) } +fn on_plus_typed(file: &SourceFile, offset: TextSize) -> Option { + let plus_token = file.syntax().token_at_offset(offset).right_biased()?; + if plus_token.kind() != SyntaxKind::PLUS { + return None; + } + let mut ancestors = plus_token.parent_ancestors(); + ancestors.next().and_then(ast::TypeBoundList::cast)?; + let trait_type = + ancestors.next().and_then(>::cast)?; + let kind = ancestors.next()?.kind(); + + if ast::RefType::can_cast(kind) || ast::PtrType::can_cast(kind) || ast::RetType::can_cast(kind) + { + let mut builder = TextEdit::builder(); + builder.insert(trait_type.syntax().text_range().start(), "(".to_owned()); + builder.insert(trait_type.syntax().text_range().end(), ")".to_owned()); + Some(builder.finish()) + } else { + None + } +} + /// Adds a space after an arrow when `fn foo() { ... }` is turned into `fn foo() -> { ... }` fn on_right_angle_typed(file: &SourceFile, offset: TextSize) -> Option { let file_text = file.syntax().text(); @@ -1594,6 +1618,66 @@ fn foo() { fn foo() { let $0 } +"#, + ); + } + + #[test] + fn adds_parentheses_around_trait_object_in_ref_type() { + type_char( + '+', + r#" +fn foo(x: &dyn A$0) {} +"#, + r#" +fn foo(x: &(dyn A+)) {} +"#, + ); + type_char( + '+', + r#" +fn foo(x: &'static dyn A$0B) {} +"#, + r#" +fn foo(x: &'static (dyn A+B)) {} +"#, + ); + type_char_noop( + '+', + r#" +fn foo(x: &(dyn A$0)) {} +"#, + ); + type_char_noop( + '+', + r#" +fn foo(x: Box) {} +"#, + ); + } + + #[test] + fn adds_parentheses_around_trait_object_in_ptr_type() { + type_char( + '+', + r#" +fn foo(x: *const dyn A$0) {} +"#, + r#" +fn foo(x: *const (dyn A+)) {} +"#, + ); + } + + #[test] + fn adds_parentheses_around_trait_object_in_return_type() { + type_char( + '+', + r#" +fn foo(x: fn() -> dyn A$0) {} +"#, + r#" +fn foo(x: fn() -> (dyn A+)) {} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs index 140ae4265be7..63701a4d15e9 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs @@ -107,7 +107,7 @@ pub(crate) fn view_memory_layout( fn read_layout( nodes: &mut Vec, db: &RootDatabase, - ty: &Type, + ty: &Type<'_>, layout: &Layout, parent_idx: usize, display_target: DisplayTarget, diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index d5cbb7328c14..adc581309d15 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -496,6 +496,7 @@ define_symbols! { vectorcall, wasm, win64, + args, array, boxed_slice, completions, diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index 89b8631cd25f..52f59679b587 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -42,7 +42,7 @@ pub fn load_workspace_at( root: &Path, cargo_config: &CargoConfig, load_config: &LoadCargoConfig, - progress: &dyn Fn(String), + progress: &(dyn Fn(String) + Sync), ) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option)> { let root = AbsPathBuf::assert_utf8(std::env::current_dir()?.join(root)); let root = ProjectManifest::discover_single(&root)?; diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs index e0c38ccf3331..4435376eab62 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs @@ -20,7 +20,9 @@ use toolchain::Tool; use crate::{ CargoConfig, CargoFeatures, CargoWorkspace, InvocationStrategy, ManifestPath, Package, Sysroot, - TargetKind, utf8_stdout, + TargetKind, + toolchain_info::{QueryConfig, version}, + utf8_stdout, }; /// Output of the build script and proc-macro building steps for a workspace. @@ -446,10 +448,30 @@ impl WorkspaceBuildScripts { } }; - if config.wrap_rustc_in_build_scripts { + // If [`--compile-time-deps` flag](https://github.com/rust-lang/cargo/issues/14434) is + // available in current toolchain's cargo, use it to build compile time deps only. + const COMP_TIME_DEPS_MIN_TOOLCHAIN_VERSION: semver::Version = semver::Version { + major: 1, + minor: 90, + patch: 0, + pre: semver::Prerelease::EMPTY, + build: semver::BuildMetadata::EMPTY, + }; + + let query_config = QueryConfig::Cargo(sysroot, manifest_path); + let toolchain = version::get(query_config, &config.extra_env).ok().flatten(); + let cargo_comp_time_deps_available = + toolchain.is_some_and(|v| v >= COMP_TIME_DEPS_MIN_TOOLCHAIN_VERSION); + + if cargo_comp_time_deps_available { + cmd.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly"); + cmd.arg("-Zunstable-options"); + cmd.arg("--compile-time-deps"); + } else if config.wrap_rustc_in_build_scripts { // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use // that to compile only proc macros and build scripts during the initial // `cargo check`. + // We don't need this if we are using `--compile-time-deps` flag. let myself = std::env::current_exe()?; cmd.env("RUSTC_WRAPPER", myself); cmd.env("RA_RUSTC_WRAPPER", "1"); diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index 1fade7b33233..58507418e4d3 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -7,16 +7,25 @@ use anyhow::Context; use base_db::Env; use cargo_metadata::{CargoOpt, MetadataCommand}; use la_arena::{Arena, Idx}; -use paths::{AbsPath, AbsPathBuf, Utf8PathBuf}; +use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf}; use rustc_hash::{FxHashMap, FxHashSet}; use serde_derive::Deserialize; use serde_json::from_value; use span::Edition; +use stdx::process::spawn_with_streaming_output; use toolchain::Tool; use crate::{CfgOverrides, InvocationStrategy}; use crate::{ManifestPath, Sysroot}; +const MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH: semver::Version = semver::Version { + major: 1, + minor: 82, + patch: 0, + pre: semver::Prerelease::EMPTY, + build: semver::BuildMetadata::EMPTY, +}; + /// [`CargoWorkspace`] represents the logical structure of, well, a Cargo /// workspace. It pretty closely mirrors `cargo metadata` output. /// @@ -290,6 +299,13 @@ pub struct CargoMetadataConfig { pub extra_args: Vec, /// Extra env vars to set when invoking the cargo command pub extra_env: FxHashMap>, + /// The target dir for this workspace load. + pub target_dir: Utf8PathBuf, + /// What kind of metadata are we fetching: workspace, rustc, or sysroot. + pub kind: &'static str, + /// The toolchain version, if known. + /// Used to conditionally enable unstable cargo features. + pub toolchain_version: Option, } // Deserialize helper for the cargo metadata @@ -382,28 +398,74 @@ impl CargoWorkspace { config.targets.iter().flat_map(|it| ["--filter-platform".to_owned(), it.clone()]), ); } - // The manifest is a rust file, so this means its a script manifest - if cargo_toml.is_rust_manifest() { - // Deliberately don't set up RUSTC_BOOTSTRAP or a nightly override here, the user should - // opt into it themselves. - other_options.push("-Zscript".to_owned()); - } - if locked { - other_options.push("--locked".to_owned()); - } if no_deps { other_options.push("--no-deps".to_owned()); } + + let mut using_lockfile_copy = false; + // The manifest is a rust file, so this means its a script manifest + if cargo_toml.is_rust_manifest() { + other_options.push("-Zscript".to_owned()); + } else if config + .toolchain_version + .as_ref() + .is_some_and(|v| *v >= MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH) + { + let lockfile = <_ as AsRef>::as_ref(cargo_toml).with_extension("lock"); + let target_lockfile = config + .target_dir + .join("rust-analyzer") + .join("metadata") + .join(config.kind) + .join("Cargo.lock"); + match std::fs::copy(&lockfile, &target_lockfile) { + Ok(_) => { + using_lockfile_copy = true; + other_options.push("--lockfile-path".to_owned()); + other_options.push(target_lockfile.to_string()); + } + Err(e) if e.kind() == std::io::ErrorKind::NotFound => { + // There exists no lockfile yet + using_lockfile_copy = true; + other_options.push("--lockfile-path".to_owned()); + other_options.push(target_lockfile.to_string()); + } + Err(e) => { + tracing::warn!( + "Failed to copy lock file from `{lockfile}` to `{target_lockfile}`: {e}", + ); + } + } + } + if using_lockfile_copy { + other_options.push("-Zunstable-options".to_owned()); + meta.env("RUSTC_BOOTSTRAP", "1"); + } + // No need to lock it if we copied the lockfile, we won't modify the original after all/ + // This way cargo cannot error out on us if the lockfile requires updating. + if !using_lockfile_copy && locked { + other_options.push("--locked".to_owned()); + } meta.other_options(other_options); // FIXME: Fetching metadata is a slow process, as it might require // calling crates.io. We should be reporting progress here, but it's // unclear whether cargo itself supports it. - progress("metadata".to_owned()); + progress("cargo metadata: started".to_owned()); - (|| -> anyhow::Result<(_, _)> { - let output = meta.cargo_command().output()?; + let res = (|| -> anyhow::Result<(_, _)> { + let mut errored = false; + let output = + spawn_with_streaming_output(meta.cargo_command(), &mut |_| (), &mut |line| { + errored = errored || line.starts_with("error") || line.starts_with("warning"); + if errored { + progress("cargo metadata: ?".to_owned()); + return; + } + progress(format!("cargo metadata: {line}")); + })?; if !output.status.success() { + progress(format!("cargo metadata: failed {}", output.status)); let error = cargo_metadata::Error::CargoMetadata { stderr: String::from_utf8(output.stderr)?, } @@ -416,8 +478,8 @@ impl CargoWorkspace { current_dir, config, sysroot, - locked, true, + locked, progress, ) { return Ok((metadata, Some(error))); @@ -431,7 +493,9 @@ impl CargoWorkspace { .ok_or(cargo_metadata::Error::NoJson)?; Ok((cargo_metadata::MetadataCommand::parse(stdout)?, None)) })() - .with_context(|| format!("Failed to run `{:?}`", meta.cargo_command())) + .with_context(|| format!("Failed to run `{:?}`", meta.cargo_command())); + progress("cargo metadata: finished".to_owned()); + res } pub fn new( diff --git a/src/tools/rust-analyzer/crates/project-model/src/manifest_path.rs b/src/tools/rust-analyzer/crates/project-model/src/manifest_path.rs index 4f43be2f38fd..fba8cc9709d1 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/manifest_path.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/manifest_path.rs @@ -1,7 +1,7 @@ //! See [`ManifestPath`]. use std::{borrow::Borrow, fmt, ops}; -use paths::{AbsPath, AbsPathBuf}; +use paths::{AbsPath, AbsPathBuf, Utf8Path}; /// More or less [`AbsPathBuf`] with non-None parent. /// @@ -78,6 +78,12 @@ impl AsRef for ManifestPath { } } +impl AsRef for ManifestPath { + fn as_ref(&self) -> &Utf8Path { + self.file.as_ref() + } +} + impl Borrow for ManifestPath { fn borrow(&self) -> &AbsPath { self.file.borrow() diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs index ebd86e3dc48a..4b34fc007112 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs @@ -4,6 +4,7 @@ //! but we can't process `.rlib` and need source code instead. The source code //! is typically installed with `rustup component add rust-src` command. +use core::fmt; use std::{env, fs, ops::Not, path::Path, process::Command}; use anyhow::{Result, format_err}; @@ -34,6 +35,19 @@ pub enum RustLibSrcWorkspace { Empty, } +impl fmt::Display for RustLibSrcWorkspace { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + RustLibSrcWorkspace::Workspace(ws) => write!(f, "workspace {}", ws.workspace_root()), + RustLibSrcWorkspace::Json(json) => write!(f, "json {}", json.manifest_or_root()), + RustLibSrcWorkspace::Stitched(stitched) => { + write!(f, "stitched with {} crates", stitched.crates.len()) + } + RustLibSrcWorkspace::Empty => write!(f, "empty"), + } + } +} + impl Sysroot { pub const fn empty() -> Sysroot { Sysroot { @@ -195,6 +209,8 @@ impl Sysroot { pub fn load_workspace( &self, sysroot_source_config: &RustSourceWorkspaceConfig, + current_dir: &AbsPath, + progress: &dyn Fn(String), ) -> Option { assert!(matches!(self.workspace, RustLibSrcWorkspace::Empty), "workspace already loaded"); let Self { root: _, rust_lib_src_root: Some(src_root), workspace: _, error: _ } = self @@ -204,10 +220,16 @@ impl Sysroot { if let RustSourceWorkspaceConfig::CargoMetadata(cargo_config) = sysroot_source_config { let library_manifest = ManifestPath::try_from(src_root.join("Cargo.toml")).unwrap(); if fs::metadata(&library_manifest).is_ok() { - if let Some(loaded) = - self.load_library_via_cargo(library_manifest, src_root, cargo_config) - { - return Some(loaded); + match self.load_library_via_cargo( + &library_manifest, + current_dir, + cargo_config, + progress, + ) { + Ok(loaded) => return Some(loaded), + Err(e) => { + tracing::error!("`cargo metadata` failed on `{library_manifest}` : {e}") + } } } tracing::debug!("Stitching sysroot library: {src_root}"); @@ -293,10 +315,11 @@ impl Sysroot { fn load_library_via_cargo( &self, - library_manifest: ManifestPath, - rust_lib_src_dir: &AbsPathBuf, + library_manifest: &ManifestPath, + current_dir: &AbsPath, cargo_config: &CargoMetadataConfig, - ) -> Option { + progress: &dyn Fn(String), + ) -> Result { tracing::debug!("Loading library metadata: {library_manifest}"); let mut cargo_config = cargo_config.clone(); // the sysroot uses `public-dependency`, so we make cargo think it's a nightly @@ -305,22 +328,16 @@ impl Sysroot { Some("nightly".to_owned()), ); - let (mut res, _) = match CargoWorkspace::fetch_metadata( - &library_manifest, - rust_lib_src_dir, + let (mut res, _) = CargoWorkspace::fetch_metadata( + library_manifest, + current_dir, &cargo_config, self, false, // Make sure we never attempt to write to the sysroot true, - &|_| (), - ) { - Ok(it) => it, - Err(e) => { - tracing::error!("`cargo metadata` failed on `{library_manifest}` : {e}"); - return None; - } - }; + progress, + )?; // Patch out `rustc-std-workspace-*` crates to point to the real crates. // This is done prior to `CrateGraph` construction to prevent de-duplication logic from failing. @@ -371,8 +388,9 @@ impl Sysroot { res.packages.remove(idx); }); - let cargo_workspace = CargoWorkspace::new(res, library_manifest, Default::default(), true); - Some(RustLibSrcWorkspace::Workspace(cargo_workspace)) + let cargo_workspace = + CargoWorkspace::new(res, library_manifest.clone(), Default::default(), true); + Ok(RustLibSrcWorkspace::Workspace(cargo_workspace)) } } diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index c69891b7463d..4f11af2d06cf 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -1,3 +1,5 @@ +use std::env::temp_dir; + use base_db::{CrateGraphBuilder, ProcMacroPaths}; use cargo_metadata::Metadata; use cfg::{CfgAtom, CfgDiff}; @@ -235,11 +237,18 @@ fn smoke_test_real_sysroot_cargo() { AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))), &Default::default(), ); - let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo()); + let cwd = AbsPathBuf::assert_utf8(temp_dir().join("smoke_test_real_sysroot_cargo")); + std::fs::create_dir_all(&cwd).unwrap(); + let loaded_sysroot = + sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo(), &cwd, &|_| ()); if let Some(loaded_sysroot) = loaded_sysroot { sysroot.set_workspace(loaded_sysroot); } - assert!(matches!(sysroot.workspace(), RustLibSrcWorkspace::Workspace(_))); + assert!( + matches!(sysroot.workspace(), RustLibSrcWorkspace::Workspace(_)), + "got {}", + sysroot.workspace() + ); let project_workspace = ProjectWorkspace { kind: ProjectWorkspaceKind::Cargo { cargo: cargo_workspace, diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index eec0077ea6e2..a6743a32b142 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -12,7 +12,7 @@ use base_db::{ }; use cfg::{CfgAtom, CfgDiff, CfgOptions}; use intern::{Symbol, sym}; -use paths::{AbsPath, AbsPathBuf}; +use paths::{AbsPath, AbsPathBuf, Utf8PathBuf}; use rustc_hash::{FxHashMap, FxHashSet}; use semver::Version; use span::{Edition, FileId}; @@ -170,7 +170,7 @@ impl ProjectWorkspace { pub fn load( manifest: ProjectManifest, config: &CargoConfig, - progress: &dyn Fn(String), + progress: &(dyn Fn(String) + Sync), ) -> anyhow::Result { ProjectWorkspace::load_inner(&manifest, config, progress) .with_context(|| format!("Failed to load the project at {manifest}")) @@ -179,7 +179,7 @@ impl ProjectWorkspace { fn load_inner( manifest: &ProjectManifest, config: &CargoConfig, - progress: &dyn Fn(String), + progress: &(dyn Fn(String) + Sync), ) -> anyhow::Result { let res = match manifest { ProjectManifest::ProjectJson(project_json) => { @@ -206,9 +206,10 @@ impl ProjectWorkspace { fn load_cargo( cargo_toml: &ManifestPath, config: &CargoConfig, - progress: &dyn Fn(String), + progress: &(dyn Fn(String) + Sync), ) -> Result { progress("Discovering sysroot".to_owned()); + let workspace_dir = cargo_toml.parent(); let CargoConfig { features, rustc_source, @@ -224,15 +225,9 @@ impl ProjectWorkspace { .. } = config; let mut sysroot = match (sysroot, sysroot_src) { - (Some(RustLibSource::Discover), None) => { - Sysroot::discover(cargo_toml.parent(), extra_env) - } + (Some(RustLibSource::Discover), None) => Sysroot::discover(workspace_dir, extra_env), (Some(RustLibSource::Discover), Some(sysroot_src)) => { - Sysroot::discover_with_src_override( - cargo_toml.parent(), - extra_env, - sysroot_src.clone(), - ) + Sysroot::discover_with_src_override(workspace_dir, extra_env, sysroot_src.clone()) } (Some(RustLibSource::Path(path)), None) => { Sysroot::discover_rust_lib_src_dir(path.clone()) @@ -248,24 +243,23 @@ impl ProjectWorkspace { let toolchain_config = QueryConfig::Cargo(&sysroot, cargo_toml); let targets = target_tuple::get(toolchain_config, target.as_deref(), extra_env).unwrap_or_default(); + let toolchain = version::get(toolchain_config, extra_env) + .inspect_err(|e| { + tracing::error!(%e, + "failed fetching toolchain version for {cargo_toml:?} workspace" + ) + }) + .ok() + .flatten(); + + let target_dir = + config.target_dir.clone().unwrap_or_else(|| workspace_dir.join("target").into()); // We spawn a bunch of processes to query various information about the workspace's // toolchain and sysroot // We can speed up loading a bit by spawning all of these processes in parallel (especially // on systems were process spawning is delayed) let join = thread::scope(|s| { - let workspace_dir = cargo_toml.parent(); - let toolchain = s.spawn(|| { - version::get(toolchain_config, extra_env) - .inspect_err(|e| { - tracing::error!(%e, - "failed fetching toolchain version for {cargo_toml:?} workspace" - ) - }) - .ok() - .flatten() - }); - let rustc_cfg = s.spawn(|| { rustc_cfg::get(toolchain_config, targets.first().map(Deref::deref), extra_env) }); @@ -300,11 +294,14 @@ impl ProjectWorkspace { targets: targets.clone(), extra_args: extra_args.clone(), extra_env: extra_env.clone(), + target_dir: target_dir.clone(), + toolchain_version: toolchain.clone(), + kind: "rustc-dev" }, &sysroot, *no_deps, - false, - &|_| (), + true, + progress, ) { Ok((meta, _error)) => { let workspace = CargoWorkspace::new( @@ -343,22 +340,31 @@ impl ProjectWorkspace { targets: targets.clone(), extra_args: extra_args.clone(), extra_env: extra_env.clone(), + target_dir: target_dir.clone(), + toolchain_version: toolchain.clone(), + kind: "workspace", }, &sysroot, *no_deps, false, - &|_| (), + progress, ) }); let loaded_sysroot = s.spawn(|| { - sysroot.load_workspace(&RustSourceWorkspaceConfig::CargoMetadata( - sysroot_metadata_config(extra_env, &targets), - )) + sysroot.load_workspace( + &RustSourceWorkspaceConfig::CargoMetadata(sysroot_metadata_config( + config, + &targets, + toolchain.clone(), + target_dir.clone(), + )), + workspace_dir, + progress, + ) }); let cargo_config_extra_env = s.spawn(|| cargo_config_env(cargo_toml, extra_env, &sysroot)); thread::Result::Ok(( - toolchain.join()?, rustc_cfg.join()?, data_layout.join()?, rustc_dir.join()?, @@ -368,18 +374,11 @@ impl ProjectWorkspace { )) }); - let ( - toolchain, - rustc_cfg, - data_layout, - rustc, - loaded_sysroot, - cargo_metadata, - cargo_config_extra_env, - ) = match join { - Ok(it) => it, - Err(e) => std::panic::resume_unwind(e), - }; + let (rustc_cfg, data_layout, rustc, loaded_sysroot, cargo_metadata, cargo_config_extra_env) = + match join { + Ok(it) => it, + Err(e) => std::panic::resume_unwind(e), + }; let (meta, error) = cargo_metadata.with_context(|| { format!( @@ -388,6 +387,7 @@ impl ProjectWorkspace { })?; let cargo = CargoWorkspace::new(meta, cargo_toml.clone(), cargo_config_extra_env, false); if let Some(loaded_sysroot) = loaded_sysroot { + tracing::info!(src_root = ?sysroot.rust_lib_src_root(), root = %loaded_sysroot, "Loaded sysroot"); sysroot.set_workspace(loaded_sysroot); } @@ -411,7 +411,7 @@ impl ProjectWorkspace { pub fn load_inline( mut project_json: ProjectJson, config: &CargoConfig, - progress: &dyn Fn(String), + progress: &(dyn Fn(String) + Sync), ) -> ProjectWorkspace { progress("Discovering sysroot".to_owned()); let mut sysroot = @@ -423,14 +423,13 @@ impl ProjectWorkspace { let query_config = QueryConfig::Rustc(&sysroot, project_json.path().as_ref()); let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env) .unwrap_or_default(); + let toolchain = version::get(query_config, &config.extra_env).ok().flatten(); // We spawn a bunch of processes to query various information about the workspace's // toolchain and sysroot // We can speed up loading a bit by spawning all of these processes in parallel (especially // on systems were process spawning is delayed) let join = thread::scope(|s| { - let toolchain = - s.spawn(|| version::get(query_config, &config.extra_env).ok().flatten()); let rustc_cfg = s.spawn(|| { rustc_cfg::get(query_config, targets.first().map(Deref::deref), &config.extra_env) }); @@ -442,24 +441,35 @@ impl ProjectWorkspace { ) }); let loaded_sysroot = s.spawn(|| { + let project_root = project_json.project_root(); if let Some(sysroot_project) = sysroot_project { - sysroot.load_workspace(&RustSourceWorkspaceConfig::Json(*sysroot_project)) + sysroot.load_workspace( + &RustSourceWorkspaceConfig::Json(*sysroot_project), + project_root, + progress, + ) } else { - sysroot.load_workspace(&RustSourceWorkspaceConfig::CargoMetadata( - sysroot_metadata_config(&config.extra_env, &targets), - )) + let target_dir = config + .target_dir + .clone() + .unwrap_or_else(|| project_root.join("target").into()); + sysroot.load_workspace( + &RustSourceWorkspaceConfig::CargoMetadata(sysroot_metadata_config( + config, + &targets, + toolchain.clone(), + target_dir, + )), + project_root, + progress, + ) } }); - thread::Result::Ok(( - toolchain.join()?, - rustc_cfg.join()?, - data_layout.join()?, - loaded_sysroot.join()?, - )) + thread::Result::Ok((rustc_cfg.join()?, data_layout.join()?, loaded_sysroot.join()?)) }); - let (toolchain, rustc_cfg, target_layout, loaded_sysroot) = match join { + let (rustc_cfg, target_layout, loaded_sysroot) = match join { Ok(it) => it, Err(e) => std::panic::resume_unwind(e), }; @@ -497,9 +507,17 @@ impl ProjectWorkspace { .unwrap_or_default(); let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env); let data_layout = target_data_layout::get(query_config, None, &config.extra_env); - let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::CargoMetadata( - sysroot_metadata_config(&config.extra_env, &targets), - )); + let target_dir = config.target_dir.clone().unwrap_or_else(|| dir.join("target").into()); + let loaded_sysroot = sysroot.load_workspace( + &RustSourceWorkspaceConfig::CargoMetadata(sysroot_metadata_config( + config, + &targets, + toolchain.clone(), + target_dir.clone(), + )), + dir, + &|_| (), + ); if let Some(loaded_sysroot) = loaded_sysroot { sysroot.set_workspace(loaded_sysroot); } @@ -512,6 +530,9 @@ impl ProjectWorkspace { targets, extra_args: config.extra_args.clone(), extra_env: config.extra_env.clone(), + target_dir, + toolchain_version: toolchain.clone(), + kind: "detached-file", }, &sysroot, config.no_deps, @@ -1804,13 +1825,18 @@ fn add_dep_inner(graph: &mut CrateGraphBuilder, from: CrateBuilderId, dep: Depen } fn sysroot_metadata_config( - extra_env: &FxHashMap>, + config: &CargoConfig, targets: &[String], + toolchain_version: Option, + target_dir: Utf8PathBuf, ) -> CargoMetadataConfig { CargoMetadataConfig { features: Default::default(), targets: targets.to_vec(), extra_args: Default::default(), - extra_env: extra_env.clone(), + extra_env: config.extra_env.clone(), + target_dir, + toolchain_version, + kind: "sysroot", } } diff --git a/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs b/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs index baac3e8bbfe7..c151cca07272 100644 --- a/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs +++ b/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs @@ -74,8 +74,8 @@ impl ToTokens for TrackedQuery { quote! { #sig { #annotation - fn #shim( - db: &dyn #trait_name, + fn #shim<'db>( + db: &'db dyn #trait_name, _input: #input_struct_name, #(#pat_and_tys),* ) #ret @@ -88,8 +88,8 @@ impl ToTokens for TrackedQuery { quote! { #sig { #annotation - fn #shim( - db: &dyn #trait_name, + fn #shim<'db>( + db: &'db dyn #trait_name, #(#pat_and_tys),* ) #ret #invoke_block diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index 12b393b80c0d..0ee01982fea2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -532,7 +532,7 @@ impl flags::AnalysisStats { } let todo = syntax::ast::make::ext::expr_todo().to_string(); - let mut formatter = |_: &hir::Type| todo.clone(); + let mut formatter = |_: &hir::Type<'_>| todo.clone(); let mut syntax_hit_found = false; for term in found_terms { let generated = term diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index e3b372c91494..740fcd81ea98 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -9,7 +9,6 @@ use hir::{ChangeWithProcMacros, Crate}; use ide::{AnalysisHost, DiagnosticCode, DiagnosticsConfig}; use ide_db::base_db; use itertools::Either; -use paths::Utf8PathBuf; use profile::StopWatch; use project_model::toolchain_info::{QueryConfig, target_data_layout}; use project_model::{ @@ -64,9 +63,9 @@ fn detect_errors_from_rustc_stderr_file(p: PathBuf) -> FxHashMap Result { - let mut path = std::env::temp_dir(); - path.push("ra-rustc-test.rs"); - let tmp_file = AbsPathBuf::try_from(Utf8PathBuf::from_path_buf(path).unwrap()).unwrap(); + let mut path = AbsPathBuf::assert_utf8(std::env::temp_dir()); + path.push("ra-rustc-test"); + let tmp_file = path.join("ra-rustc-test.rs"); std::fs::write(&tmp_file, "")?; let cargo_config = CargoConfig { sysroot: Some(RustLibSource::Discover), @@ -76,7 +75,8 @@ impl Tester { }; let mut sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env); - let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo()); + let loaded_sysroot = + sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo(), &path, &|_| ()); if let Some(loaded_sysroot) = loaded_sysroot { sysroot.set_workspace(loaded_sysroot); } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 762b63f54b09..05e1b832cd16 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -452,6 +452,8 @@ config_data! { assist_emitMustUse: bool = false, /// Placeholder expression to use for missing expressions in assists. assist_expressionFillDefault: ExprFillDefaultDef = ExprFillDefaultDef::Todo, + /// When inserting a type (e.g. in "fill match arms" assist), prefer to use `Self` over the type name where possible. + assist_preferSelf: bool = false, /// Enable borrow checking for term search code assists. If set to false, also there will be more suggestions, but some of them may not borrow-check. assist_termSearch_borrowcheck: bool = true, /// Term search fuel in "units of work" for assists (Defaults to 1800). @@ -760,7 +762,11 @@ config_data! { /// though Cargo might be the eventual consumer. vfs_extraIncludes: Vec = vec![], - /// Exclude imports from symbol search. + /// Exclude all imports from workspace symbol search. + /// + /// In addition to regular imports (which are always excluded), + /// this option removes public imports (better known as re-exports) + /// and removes imports that rename the imported symbol. workspace_symbol_search_excludeImports: bool = false, /// Workspace symbol search kind. workspace_symbol_search_kind: WorkspaceSymbolSearchKindDef = WorkspaceSymbolSearchKindDef::OnlyTypes, @@ -1505,6 +1511,7 @@ impl Config { ExprFillDefaultDef::Default => ExprFillDefaultMode::Default, ExprFillDefaultDef::Underscore => ExprFillDefaultMode::Underscore, }, + prefer_self_ty: *self.assist_preferSelf(source_root), } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs index b7373f274f05..200e972e4289 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs @@ -239,7 +239,7 @@ pub(crate) fn handle_did_change_configuration( let (config, e, _) = config.apply_change(change); this.config_errors = e.is_empty().not().then_some(e); - // Client config changes neccesitates .update_config method to be called. + // Client config changes necessitates .update_config method to be called. this.update_configuration(config); } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs index 418fe957590d..04e31f37fd2c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs @@ -77,7 +77,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { _ => Some(OneOf::Left(false)), }, document_on_type_formatting_provider: Some({ - let mut chars = ide::Analysis::SUPPORTED_TRIGGER_CHARS.chars(); + let mut chars = ide::Analysis::SUPPORTED_TRIGGER_CHARS.iter(); DocumentOnTypeFormattingOptions { first_trigger_character: chars.next().unwrap().to_string(), more_trigger_character: Some(chars.map(|c| c.to_string()).collect()), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 4677880daaf9..189d95ec7ed4 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -114,6 +114,16 @@ impl GlobalState { Durability::HIGH, ); } + + if self.config.cargo(None) != old_config.cargo(None) { + let req = FetchWorkspaceRequest { path: None, force_crate_graph_reload: false }; + self.fetch_workspaces_queue.request_op("cargo config changed".to_owned(), req) + } + + if self.config.cfg_set_test(None) != old_config.cfg_set_test(None) { + let req = FetchWorkspaceRequest { path: None, force_crate_graph_reload: false }; + self.fetch_workspaces_queue.request_op("cfg_set_test config changed".to_owned(), req) + } } pub(crate) fn current_status(&self) -> lsp_ext::ServerStatusParams { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs index 9c0bc33af646..e7528dbc9396 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs @@ -103,6 +103,7 @@ impl CargoTestHandle { ) -> std::io::Result { let mut cmd = toolchain::command(Tool::Cargo.path(), root, &options.extra_env); cmd.env("RUSTC_BOOTSTRAP", "1"); + cmd.arg("--color=always"); cmd.arg("test"); cmd.arg("--package"); diff --git a/src/tools/rust-analyzer/crates/stdx/src/lib.rs b/src/tools/rust-analyzer/crates/stdx/src/lib.rs index 9a292eacd7f7..978c50d807bc 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/lib.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/lib.rs @@ -13,6 +13,7 @@ pub mod panic_context; pub mod process; pub mod rand; pub mod thread; +pub mod variance; pub use itertools; diff --git a/src/tools/rust-analyzer/crates/stdx/src/variance.rs b/src/tools/rust-analyzer/crates/stdx/src/variance.rs new file mode 100644 index 000000000000..8465d72bf371 --- /dev/null +++ b/src/tools/rust-analyzer/crates/stdx/src/variance.rs @@ -0,0 +1,270 @@ +//! This is a copy of [`std::marker::variance`]. + +use std::any::type_name; +use std::cmp::Ordering; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::marker::PhantomData; + +macro_rules! first_token { + ($first:tt $($rest:tt)*) => { + $first + }; +} +macro_rules! phantom_type { + ($( + $(#[$attr:meta])* + pub struct $name:ident <$t:ident> ($($inner:tt)*); + )*) => {$( + $(#[$attr])* + pub struct $name<$t>($($inner)*) where T: ?Sized; + + impl $name + where T: ?Sized + { + /// Constructs a new instance of the variance marker. + pub const fn new() -> Self { + Self(PhantomData) + } + } + + impl self::sealed::Sealed for $name where T: ?Sized { + const VALUE: Self = Self::new(); + } + + impl Variance for $name where T: ?Sized {} + + impl Default for $name + where T: ?Sized + { + fn default() -> Self { + Self(PhantomData) + } + } + + impl fmt::Debug for $name + where T: ?Sized + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}<{}>", stringify!($name), type_name::()) + } + } + + impl Clone for $name + where T: ?Sized + { + fn clone(&self) -> Self { + *self + } + } + + impl Copy for $name where T: ?Sized {} + + impl PartialEq for $name + where T: ?Sized + { + fn eq(&self, _: &Self) -> bool { + true + } + } + + impl Eq for $name where T: ?Sized {} + + #[allow(clippy::non_canonical_partial_ord_impl)] + impl PartialOrd for $name + where T: ?Sized + { + fn partial_cmp(&self, _: &Self) -> Option { + Some(Ordering::Equal) + } + } + + impl Ord for $name + where T: ?Sized + { + fn cmp(&self, _: &Self) -> Ordering { + Ordering::Equal + } + } + + impl Hash for $name + where T: ?Sized + { + fn hash(&self, _: &mut H) {} + } + )*}; +} + +macro_rules! phantom_lifetime { + ($( + $(#[$attr:meta])* + pub struct $name:ident <$lt:lifetime> ($($inner:tt)*); + )*) => {$( + $(#[$attr])* + + #[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct $name<$lt>($($inner)*); + + impl $name<'_> { + /// Constructs a new instance of the variance marker. + pub const fn new() -> Self { + Self(first_token!($($inner)*)(PhantomData)) + } + } + + impl self::sealed::Sealed for $name<'_> { + const VALUE: Self = Self::new(); + } + + impl Variance for $name<'_> {} + + impl fmt::Debug for $name<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", stringify!($name)) + } + } + )*}; +} + +phantom_lifetime! { + /// Zero-sized type used to mark a lifetime as covariant. + /// + /// Covariant lifetimes must live at least as long as declared. See [the reference][1] for more + /// information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `'a`, the following are guaranteed: + /// * `size_of::>() == 0` + /// * `align_of::>() == 1` + + pub struct PhantomCovariantLifetime<'a>(PhantomCovariant<&'a ()>); + /// Zero-sized type used to mark a lifetime as contravariant. + /// + /// Contravariant lifetimes must live at most as long as declared. See [the reference][1] for + /// more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `'a`, the following are guaranteed: + /// * `size_of::>() == 0` + /// * `align_of::>() == 1` + + pub struct PhantomContravariantLifetime<'a>(PhantomContravariant<&'a ()>); + /// Zero-sized type used to mark a lifetime as invariant. + /// + /// Invariant lifetimes must be live for the exact length declared, neither shorter nor longer. + /// See [the reference][1] for more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `'a`, the following are guaranteed: + /// * `size_of::>() == 0` + /// * `align_of::>() == 1` + + pub struct PhantomInvariantLifetime<'a>(PhantomInvariant<&'a ()>); + +} + +phantom_type! { + /// Zero-sized type used to mark a type parameter as covariant. + /// + /// Types used as part of the return value from a function are covariant. If the type is _also_ + /// passed as a parameter then it is [invariant][PhantomInvariant]. See [the reference][1] for + /// more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `T`, the following are guaranteed: + /// * `size_of::>() == 0` + /// * `align_of::>() == 1` + + pub struct PhantomCovariant(PhantomData T>); + /// Zero-sized type used to mark a type parameter as contravariant. + /// + /// Types passed as arguments to a function are contravariant. If the type is _also_ part of the + /// return value from a function then it is [invariant][PhantomInvariant]. See [the + /// reference][1] for more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `T`, the following are guaranteed: + /// * `size_of::>() == 0` + /// * `align_of::>() == 1` + + pub struct PhantomContravariant(PhantomData); + /// Zero-sized type used to mark a type parameter as invariant. + /// + /// Types that are both passed as an argument _and_ used as part of the return value from a + /// function are invariant. See [the reference][1] for more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `T`, the following are guaranteed: + /// * `size_of::>() == 0` + /// * `align_of::>() == 1` + + pub struct PhantomInvariant(PhantomData T>); + +} + +mod sealed { + + pub trait Sealed { + const VALUE: Self; + } +} +/// A marker trait for phantom variance types. +pub trait Variance: sealed::Sealed + Default {} +/// Construct a variance marker; equivalent to [`Default::default`]. +/// +/// This type can be any of the following. You generally should not need to explicitly name the +/// type, however. +/// +/// - [`PhantomCovariant`] +/// - [`PhantomContravariant`] +/// - [`PhantomInvariant`] +/// - [`PhantomCovariantLifetime`] +/// - [`PhantomContravariantLifetime`] +/// - [`PhantomInvariantLifetime`] +/// +/// # Example +/// +/// ```rust +/// #![feature(phantom_variance_markers)] +/// +/// use core::marker::{PhantomCovariant, variance}; +/// +/// struct BoundFn +/// where +/// F: Fn(P) -> R, +/// { +/// function: F, +/// parameter: P, +/// return_value: PhantomCovariant, +/// } +/// +/// let bound_fn = BoundFn { +/// function: core::convert::identity, +/// parameter: 5u8, +/// return_value: variance(), +/// }; +/// ``` +pub const fn variance() -> T +where + T: Variance, +{ + T::VALUE +} diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs index fab4cb287c3d..955aadaa25d3 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -134,6 +134,13 @@ pub fn name_ref(name_ref: &str) -> ast::NameRef { } } } +pub fn name_ref_self_ty() -> ast::NameRef { + quote! { + NameRef { + [Self] + } + } +} fn raw_ident_esc(ident: &str) -> &'static str { if is_raw_identifier(ident, Edition::CURRENT) { "r#" } else { "" } } diff --git a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs index 7240069753e8..1d821e96e550 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs @@ -412,22 +412,36 @@ impl MiniCore { } let mut active_regions = Vec::new(); + let mut inactive_regions = Vec::new(); let mut seen_regions = Vec::new(); for line in lines { let trimmed = line.trim(); if let Some(region) = trimmed.strip_prefix("// region:") { - active_regions.push(region); - continue; + if let Some(region) = region.strip_prefix('!') { + inactive_regions.push(region); + continue; + } else { + active_regions.push(region); + continue; + } } if let Some(region) = trimmed.strip_prefix("// endregion:") { - let prev = active_regions.pop().unwrap(); + let (prev, region) = if let Some(region) = region.strip_prefix('!') { + (inactive_regions.pop().unwrap(), region) + } else { + (active_regions.pop().unwrap(), region) + }; assert_eq!(prev, region, "unbalanced region pairs"); continue; } - let mut line_region = false; - if let Some(idx) = trimmed.find("// :") { - line_region = true; + let mut active_line_region = false; + let mut inactive_line_region = false; + if let Some(idx) = trimmed.find("// :!") { + inactive_line_region = true; + inactive_regions.push(&trimmed[idx + "// :!".len()..]); + } else if let Some(idx) = trimmed.find("// :") { + active_line_region = true; active_regions.push(&trimmed[idx + "// :".len()..]); } @@ -438,18 +452,30 @@ impl MiniCore { seen_regions.push(region); keep &= self.has_flag(region); } + for ®ion in &inactive_regions { + assert!(!region.starts_with(' '), "region marker starts with a space: {region:?}"); + self.assert_valid_flag(region); + seen_regions.push(region); + keep &= !self.has_flag(region); + } if keep { buf.push_str(line); } - if line_region { + if active_line_region { active_regions.pop().unwrap(); } + if inactive_line_region { + inactive_regions.pop().unwrap(); + } } if !active_regions.is_empty() { panic!("unclosed regions: {active_regions:?} Add an `endregion` comment"); } + if !inactive_regions.is_empty() { + panic!("unclosed regions: {inactive_regions:?} Add an `endregion` comment"); + } for flag in &self.valid_flags { if !seen_regions.iter().any(|it| it == flag) { diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index 4bdd791eb167..d13a81d287fa 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -31,6 +31,7 @@ //! eq: sized //! error: fmt //! fmt: option, result, transmute, coerce_unsized, copy, clone, derive +//! fmt_before_1_89_0: fmt //! fn: tuple //! from: sized, result //! future: pin @@ -1175,6 +1176,7 @@ pub mod fmt { } } + // region:fmt_before_1_89_0 #[lang = "format_unsafe_arg"] pub struct UnsafeArg { _private: (), @@ -1185,6 +1187,7 @@ pub mod fmt { UnsafeArg { _private: () } } } + // endregion:fmt_before_1_89_0 } #[derive(Copy, Clone)] @@ -1204,6 +1207,7 @@ pub mod fmt { Arguments { pieces, fmt: None, args: &[] } } + // region:fmt_before_1_89_0 pub fn new_v1_formatted( pieces: &'a [&'static str], args: &'a [rt::Argument<'a>], @@ -1212,6 +1216,17 @@ pub mod fmt { ) -> Arguments<'a> { Arguments { pieces, fmt: Some(fmt), args } } + // endregion:fmt_before_1_89_0 + + // region:!fmt_before_1_89_0 + pub unsafe fn new_v1_formatted( + pieces: &'a [&'static str], + args: &'a [rt::Argument<'a>], + fmt: &'a [rt::Placeholder], + ) -> Arguments<'a> { + Arguments { pieces, fmt: Some(fmt), args } + } + // endregion:!fmt_before_1_89_0 pub const fn as_str(&self) -> Option<&'static str> { match (self.pieces, self.args) { diff --git a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md index 4eb9cfc4e5bd..9404b1454a08 100644 --- a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md @@ -13,6 +13,13 @@ Default: `"todo"` Placeholder expression to use for missing expressions in assists. +## rust-analyzer.assist.preferSelf {#assist.preferSelf} + +Default: `false` + +When inserting a type (e.g. in "fill match arms" assist), prefer to use `Self` over the type name where possible. + + ## rust-analyzer.assist.termSearch.borrowcheck {#assist.termSearch.borrowcheck} Default: `true` @@ -1535,7 +1542,11 @@ https://github.com/facebook/buck2/tree/main/integrations/rust-project. Default: `false` -Exclude imports from symbol search. +Exclude all imports from workspace symbol search. + +In addition to regular imports (which are always excluded), +this option removes public imports (better known as re-exports) +and removes imports that rename the imported symbol. ## rust-analyzer.workspace.symbol.search.kind {#workspace.symbol.search.kind} diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index dcdb4fe30ee8..26a21c1468d8 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -680,6 +680,16 @@ } } }, + { + "title": "assist", + "properties": { + "rust-analyzer.assist.preferSelf": { + "markdownDescription": "When inserting a type (e.g. in \"fill match arms\" assist), prefer to use `Self` over the type name where possible.", + "default": false, + "type": "boolean" + } + } + }, { "title": "assist", "properties": { @@ -2895,7 +2905,7 @@ "title": "workspace", "properties": { "rust-analyzer.workspace.symbol.search.excludeImports": { - "markdownDescription": "Exclude imports from symbol search.", + "markdownDescription": "Exclude all imports from workspace symbol search.\n\nIn addition to regular imports (which are always excluded),\nthis option removes public imports (better known as re-exports)\nand removes imports that rename the imported symbol.", "default": false, "type": "boolean" } diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts index f36e18a73da0..d2dc740c09b5 100644 --- a/src/tools/rust-analyzer/editors/code/src/config.ts +++ b/src/tools/rust-analyzer/editors/code/src/config.ts @@ -20,15 +20,9 @@ export class Config { configureLang: vscode.Disposable | undefined; readonly rootSection = "rust-analyzer"; - private readonly requiresServerReloadOpts = [ - "cargo", - "procMacro", - "serverPath", - "server", - "files", - "cfg", - "showSyntaxTree", - ].map((opt) => `${this.rootSection}.${opt}`); + private readonly requiresServerReloadOpts = ["server", "files", "showSyntaxTree"].map( + (opt) => `${this.rootSection}.${opt}`, + ); private readonly requiresWindowReloadOpts = ["testExplorer"].map( (opt) => `${this.rootSection}.${opt}`, @@ -208,7 +202,7 @@ export class Config { } get serverPath() { - return this.get("server.path") ?? this.get("serverPath"); + return this.get("server.path"); } get serverExtraEnv(): Env { diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version index af0dd5c9acda..a454087b0cdc 100644 --- a/src/tools/rust-analyzer/rust-version +++ b/src/tools/rust-analyzer/rust-version @@ -1 +1 @@ -7c10378e1fee5ddc6573b916aeb884ab10e0de17 +27733d46d79f4eb92e240fbba502c43022665735 diff --git a/src/tools/rust-installer/install-template.sh b/src/tools/rust-installer/install-template.sh index f7f408be882e..337aaa95b9a2 100644 --- a/src/tools/rust-installer/install-template.sh +++ b/src/tools/rust-installer/install-template.sh @@ -160,7 +160,7 @@ valopt() { local doc="$*" if [ $HELP -eq 0 ] then - local uop=$(echo $op | tr 'a-z-' 'A-Z_') + local uop=$(echo $op | tr '[a-z]-' '[A-Z]_') local v="CFG_${uop}" eval $v="$default" for arg in $CFG_ARGS @@ -206,8 +206,8 @@ opt() { do if [ "$arg" = "--${flag}-${op}" ] then - op=$(echo $op | tr 'a-z-' 'A-Z_') - flag=$(echo $flag | tr 'a-z' 'A-Z') + op=$(echo $op | tr '[a-z]-' '[A-Z]_') + flag=$(echo $flag | tr '[a-z]' '[A-Z]') local v="CFG_${flag}_${op}" eval $v=1 putvar $v @@ -235,7 +235,7 @@ flag() { do if [ "$arg" = "--${op}" ] then - op=$(echo $op | tr 'a-z-' 'A-Z_') + op=$(echo $op | tr '[a-z]-' '[A-Z]_') local v="CFG_${op}" eval $v=1 putvar $v diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index ed67fa7d1a9e..7bf3bb195ee0 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -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", ] diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index be6b483bfff1..08aedff2b20d 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -2289,8 +2289,10 @@ fn rewrite_expr_addrof( ) -> RewriteResult { let operator_str = match (mutability, borrow_kind) { (ast::Mutability::Not, ast::BorrowKind::Ref) => "&", + (ast::Mutability::Not, ast::BorrowKind::Pin) => "&pin const ", (ast::Mutability::Not, ast::BorrowKind::Raw) => "&raw const ", (ast::Mutability::Mut, ast::BorrowKind::Ref) => "&mut ", + (ast::Mutability::Mut, ast::BorrowKind::Pin) => "&pin mut ", (ast::Mutability::Mut, ast::BorrowKind::Raw) => "&raw mut ", }; rewrite_unary_prefix(context, operator_str, expr, shape) diff --git a/src/tools/rustfmt/src/imports.rs b/src/tools/rustfmt/src/imports.rs index b741dd9b5da5..788fed013ad2 100644 --- a/src/tools/rustfmt/src/imports.rs +++ b/src/tools/rustfmt/src/imports.rs @@ -184,7 +184,7 @@ impl UseSegment { modsep: bool, ) -> Option { let name = rewrite_ident(context, path_seg.ident); - if name.is_empty() || name == "{{root}}" { + if name.is_empty() { return None; } let kind = match name { diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index afd847f95157..10e2809e58bf 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -5,7 +5,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter, SilentEmitter, stderr_destination}; use rustc_errors::registry::Registry; -use rustc_errors::translation::Translate; +use rustc_errors::translation::Translator; use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel}; use rustc_session::parse::ParseSess as RawParseSess; use rustc_span::{ @@ -47,16 +47,6 @@ impl SilentOnIgnoredFilesEmitter { } } -impl Translate for SilentOnIgnoredFilesEmitter { - fn fluent_bundle(&self) -> Option<&rustc_errors::FluentBundle> { - self.emitter.fluent_bundle() - } - - fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { - self.emitter.fallback_fluent_bundle() - } -} - impl Emitter for SilentOnIgnoredFilesEmitter { fn source_map(&self) -> Option<&SourceMap> { None @@ -84,6 +74,10 @@ impl Emitter for SilentOnIgnoredFilesEmitter { } self.handle_non_ignoreable_error(diag, registry); } + + fn translator(&self) -> &Translator { + self.emitter.translator() + } } impl From for ColorConfig { @@ -110,23 +104,15 @@ fn default_dcx( ColorConfig::Never }; - let fallback_bundle = rustc_errors::fallback_fluent_bundle( - rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), - false, - ); - let emitter = Box::new( - HumanEmitter::new(stderr_destination(emit_color), fallback_bundle) - .sm(Some(source_map.clone())), - ); + let translator = rustc_driver::default_translator(); - let emitter: Box = if !show_parse_errors { - Box::new(SilentEmitter { - fatal_emitter: emitter, - fatal_note: None, - emit_fatal_diagnostic: false, - }) + let emitter: Box = if show_parse_errors { + Box::new( + HumanEmitter::new(stderr_destination(emit_color), translator) + .sm(Some(source_map.clone())), + ) } else { - emitter + Box::new(SilentEmitter { translator }) }; DiagCtxt::new(Box::new(SilentOnIgnoredFilesEmitter { has_non_ignorable_parser_errors: false, @@ -205,7 +191,7 @@ impl ParseSess { } pub(crate) fn set_silent_emitter(&mut self) { - self.raw_psess.dcx().make_silent(None, false); + self.raw_psess.dcx().make_silent(); } pub(crate) fn span_to_filename(&self, span: Span) -> FileName { @@ -335,16 +321,6 @@ mod tests { num_emitted_errors: Arc, } - impl Translate for TestEmitter { - fn fluent_bundle(&self) -> Option<&rustc_errors::FluentBundle> { - None - } - - fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { - panic!("test emitter attempted to translate a diagnostic"); - } - } - impl Emitter for TestEmitter { fn source_map(&self) -> Option<&SourceMap> { None @@ -353,6 +329,10 @@ mod tests { fn emit_diagnostic(&mut self, _diag: DiagInner, _registry: &Registry) { self.num_emitted_errors.fetch_add(1, Ordering::Release); } + + fn translator(&self) -> &Translator { + panic!("test emitter attempted to translate a diagnostic"); + } } fn build_diagnostic(level: DiagnosticLevel, span: Option) -> DiagInner { diff --git a/src/tools/rustfmt/tests/source/pin_sugar.rs b/src/tools/rustfmt/tests/source/pin_sugar.rs index 370dfbc196ae..e5b47339b928 100644 --- a/src/tools/rustfmt/tests/source/pin_sugar.rs +++ b/src/tools/rustfmt/tests/source/pin_sugar.rs @@ -18,3 +18,13 @@ impl Foo { mut self) {} fn i(&pin mut self) {} } + +fn borrows() { + let mut foo = 0_i32; + let x: Pin<&mut _> = & pin + mut foo; + + let x: Pin<&_> = & + pin const + foo; +} diff --git a/src/tools/rustfmt/tests/target/pin_sugar.rs b/src/tools/rustfmt/tests/target/pin_sugar.rs index 7d04efb1b326..09ad23a5807f 100644 --- a/src/tools/rustfmt/tests/target/pin_sugar.rs +++ b/src/tools/rustfmt/tests/target/pin_sugar.rs @@ -16,3 +16,10 @@ impl Foo { fn h<'a>(&'a pin mut self) {} fn i(&pin mut self) {} } + +fn borrows() { + let mut foo = 0_i32; + let x: Pin<&mut _> = &pin mut foo; + + let x: Pin<&_> = &pin const foo; +} diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 170dcd626a28..bf813d2131e8 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -206,6 +206,7 @@ const EXCEPTIONS_CRANELIFT: ExceptionList = &[ ("regalloc2", "Apache-2.0 WITH LLVM-exception"), ("target-lexicon", "Apache-2.0 WITH LLVM-exception"), ("wasmtime-jit-icache-coherence", "Apache-2.0 WITH LLVM-exception"), + ("wasmtime-math", "Apache-2.0 WITH LLVM-exception"), // tidy-alphabetical-end ]; @@ -356,6 +357,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "rand", "rand_chacha", "rand_core", + "rand_xorshift", // dependency for doc-tests in rustc_thread_pool "rand_xoshiro", "redox_syscall", "regex", @@ -364,7 +366,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "rustc-demangle", "rustc-hash", "rustc-literal-escaper", - "rustc-rayon-core", "rustc-stable-hash", "rustc_apfloat", "rustix", @@ -373,6 +374,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "scoped-tls", "scopeguard", "self_cell", + "semver", "serde", "serde_derive", "serde_json", @@ -537,6 +539,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "indexmap", "libc", "libloading", + "libm", "log", "mach2", "memchr", @@ -554,6 +557,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "target-lexicon", "unicode-ident", "wasmtime-jit-icache-coherence", + "wasmtime-math", "windows-sys", "windows-targets", "windows_aarch64_gnullvm", diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index e2d1b85797ff..bb61412f6788 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -43,9 +43,18 @@ macro_rules! verbose_print { }; } -pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut bool) { +pub fn check( + root_path: &Path, + search_paths: &[&Path], + verbose: bool, + ci_info: &crate::CiInfo, + bad: &mut bool, +) { let mut errors = Vec::new(); + // Check that no error code explanation was removed. + check_removed_error_code_explanation(ci_info, bad); + // Stage 1: create list let error_codes = extract_error_codes(root_path, &mut errors); if verbose { @@ -68,6 +77,27 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut } } +fn check_removed_error_code_explanation(ci_info: &crate::CiInfo, bad: &mut bool) { + let Some(base_commit) = &ci_info.base_commit else { + eprintln!("Skipping error code explanation removal check"); + return; + }; + let Some(diff) = crate::git_diff(base_commit, "--name-status") else { + *bad = true; + eprintln!("removed error code explanation tidy check: Failed to run git diff"); + return; + }; + if diff.lines().any(|line| { + line.starts_with('D') && line.contains("compiler/rustc_error_codes/src/error_codes/") + }) { + *bad = true; + eprintln!("tidy check error: Error code explanations should never be removed!"); + eprintln!("Take a look at E0001 to see how to handle it."); + return; + } + println!("No error code explanation was removed!"); +} + /// Stage 1: Parses a list of error codes from `error_codes.rs`. fn extract_error_codes(root_path: &Path, errors: &mut Vec) -> Vec { let path = root_path.join(Path::new(ERROR_CODES_PATH)); diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 045f2f0692a1..24356c31da49 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -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 @@ -2071,7 +2070,6 @@ ui/issues/issue-32782.rs ui/issues/issue-32797.rs ui/issues/issue-32805.rs ui/issues/issue-3290.rs -ui/issues/issue-32950.rs ui/issues/issue-32995-2.rs ui/issues/issue-32995.rs ui/issues/issue-33202.rs @@ -2341,7 +2339,6 @@ ui/issues/issue-49934.rs ui/issues/issue-49955.rs ui/issues/issue-49973.rs ui/issues/issue-50187.rs -ui/issues/issue-50403.rs ui/issues/issue-50411.rs ui/issues/issue-50415.rs ui/issues/issue-50442.rs diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index e8a12d563358..237737f0f169 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -3,6 +3,12 @@ //! This library contains the tidy lints and exposes it //! to be used by tools. +use std::ffi::OsStr; +use std::process::Command; + +use build_helper::ci::CiEnv; +use build_helper::git::{GitConfig, get_closest_upstream_commit}; +use build_helper::stage0_parser::{Stage0Config, parse_stage0_file}; use termcolor::WriteColor; macro_rules! static_regex { @@ -63,6 +69,61 @@ fn tidy_error(args: &str) -> std::io::Result<()> { Ok(()) } +pub struct CiInfo { + pub git_merge_commit_email: String, + pub nightly_branch: String, + pub base_commit: Option, + pub ci_env: CiEnv, +} + +impl CiInfo { + pub fn new(bad: &mut bool) -> Self { + let stage0 = parse_stage0_file(); + let Stage0Config { nightly_branch, git_merge_commit_email, .. } = stage0.config; + + let mut info = Self { + nightly_branch, + git_merge_commit_email, + ci_env: CiEnv::current(), + base_commit: None, + }; + let base_commit = match get_closest_upstream_commit(None, &info.git_config(), info.ci_env) { + Ok(Some(commit)) => Some(commit), + Ok(None) => { + info.error_if_in_ci("no base commit found", bad); + None + } + Err(error) => { + info.error_if_in_ci(&format!("failed to retrieve base commit: {error}"), bad); + None + } + }; + info.base_commit = base_commit; + info + } + + pub fn git_config(&self) -> GitConfig<'_> { + GitConfig { + nightly_branch: &self.nightly_branch, + git_merge_commit_email: &self.git_merge_commit_email, + } + } + + pub fn error_if_in_ci(&self, msg: &str, bad: &mut bool) { + if self.ci_env.is_running_in_ci() { + *bad = true; + eprintln!("tidy check error: {msg}"); + } else { + eprintln!("tidy check warning: {msg}. Some checks will be skipped."); + } + } +} + +pub fn git_diff>(base_commit: &str, extra_arg: S) -> Option { + let output = Command::new("git").arg("diff").arg(base_commit).arg(extra_arg).output().ok()?; + Some(String::from_utf8_lossy(&output.stdout).into()) +} + pub mod alphabetical; pub mod bins; pub mod debug_artifacts; @@ -83,6 +144,7 @@ pub mod pal; pub mod rustdoc_css_themes; pub mod rustdoc_gui_tests; pub mod rustdoc_js; +pub mod rustdoc_json; pub mod rustdoc_templates; pub mod style; pub mod target_policy; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 776f1bde2eb7..ef6ff5c9277a 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -48,7 +48,9 @@ fn main() { let extra_checks = cfg_args.iter().find(|s| s.starts_with("--extra-checks=")).map(String::as_str); - let bad = std::sync::Arc::new(AtomicBool::new(false)); + let mut bad = false; + let ci_info = CiInfo::new(&mut bad); + let bad = std::sync::Arc::new(AtomicBool::new(bad)); let drain_handles = |handles: &mut VecDeque>| { // poll all threads for completion before awaiting the oldest one @@ -110,11 +112,12 @@ fn main() { check!(rustdoc_css_themes, &librustdoc_path); check!(rustdoc_templates, &librustdoc_path); check!(rustdoc_js, &librustdoc_path, &tools_path, &src_path); + check!(rustdoc_json, &src_path, &ci_info); check!(known_bug, &crashes_path); check!(unknown_revision, &tests_path); // Checks that only make sense for the compiler. - check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose); + check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose, &ci_info); check!(fluent_alphabetical, &compiler_path, bless); check!(fluent_period, &compiler_path); check!(target_policy, &root_path); diff --git a/src/tools/tidy/src/rustdoc_js.rs b/src/tools/tidy/src/rustdoc_js.rs index 2517e2de12ce..720f0712ee03 100644 --- a/src/tools/tidy/src/rustdoc_js.rs +++ b/src/tools/tidy/src/rustdoc_js.rs @@ -62,6 +62,9 @@ pub fn check(librustdoc_path: &Path, tools_path: &Path, src_path: &Path, bad: &m return; } }; + // Having the correct `eslint` version installed via `npm` isn't strictly necessary, since we're invoking it via `npx`, + // but this check allows the vast majority that is not working on the rustdoc frontend to avoid the penalty of running + // `eslint` in tidy. See also: https://github.com/rust-lang/rust/pull/142851 match get_eslint_version() { Some(version) => { if version != eslint_version { diff --git a/src/tools/tidy/src/rustdoc_json.rs b/src/tools/tidy/src/rustdoc_json.rs new file mode 100644 index 000000000000..dfbb35d69f17 --- /dev/null +++ b/src/tools/tidy/src/rustdoc_json.rs @@ -0,0 +1,90 @@ +//! Tidy check to ensure that `FORMAT_VERSION` was correctly updated if `rustdoc-json-types` was +//! updated as well. + +use std::path::Path; +use std::str::FromStr; + +const RUSTDOC_JSON_TYPES: &str = "src/rustdoc-json-types"; + +pub fn check(src_path: &Path, ci_info: &crate::CiInfo, bad: &mut bool) { + println!("Checking tidy rustdoc_json..."); + let Some(base_commit) = &ci_info.base_commit else { + eprintln!("No base commit, skipping rustdoc_json check"); + return; + }; + + // First we check that `src/rustdoc-json-types` was modified. + match crate::git_diff(&base_commit, "--name-status") { + Some(output) => { + if !output + .lines() + .any(|line| line.starts_with("M") && line.contains(RUSTDOC_JSON_TYPES)) + { + // `rustdoc-json-types` was not modified so nothing more to check here. + println!("`rustdoc-json-types` was not modified."); + return; + } + } + None => { + *bad = true; + eprintln!("error: failed to run `git diff` in rustdoc_json check"); + return; + } + } + // Then we check that if `FORMAT_VERSION` was updated, the `Latest feature:` was also updated. + match crate::git_diff(&base_commit, src_path.join("rustdoc-json-types")) { + Some(output) => { + let mut format_version_updated = false; + let mut latest_feature_comment_updated = false; + let mut new_version = None; + let mut old_version = None; + for line in output.lines() { + if line.starts_with("+pub const FORMAT_VERSION: u32 =") { + format_version_updated = true; + new_version = line + .split('=') + .nth(1) + .and_then(|s| s.trim().split(';').next()) + .and_then(|s| u32::from_str(s.trim()).ok()); + } else if line.starts_with("-pub const FORMAT_VERSION: u32 =") { + old_version = line + .split('=') + .nth(1) + .and_then(|s| s.trim().split(';').next()) + .and_then(|s| u32::from_str(s.trim()).ok()); + } else if line.starts_with("+// Latest feature:") { + latest_feature_comment_updated = true; + } + } + if format_version_updated != latest_feature_comment_updated { + *bad = true; + if latest_feature_comment_updated { + eprintln!( + "error in `rustdoc_json` tidy check: `Latest feature` comment was updated \ + whereas `FORMAT_VERSION` wasn't in `{RUSTDOC_JSON_TYPES}/lib.rs`" + ); + } else { + eprintln!( + "error in `rustdoc_json` tidy check: `Latest feature` comment was not \ + updated whereas `FORMAT_VERSION` was in `{RUSTDOC_JSON_TYPES}/lib.rs`" + ); + } + } + match (new_version, old_version) { + (Some(new_version), Some(old_version)) if new_version != old_version + 1 => { + *bad = true; + eprintln!( + "error in `rustdoc_json` tidy check: invalid `FORMAT_VERSION` increase in \ + `{RUSTDOC_JSON_TYPES}/lib.rs`, should be `{}`, found `{new_version}`", + old_version + 1, + ); + } + _ => {} + } + } + None => { + *bad = true; + eprintln!("error: failed to run `git diff` in rustdoc_json check"); + } + } +} diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 8f9b07c49acb..53226fcb80e6 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -17,7 +17,7 @@ use ignore::Walk; const ENTRY_LIMIT: u32 = 901; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1623; +const ISSUES_ENTRY_LIMIT: u32 = 1619; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml index 642d48b9952e..ce718902b29f 100644 --- a/src/tools/wasm-component-ld/Cargo.toml +++ b/src/tools/wasm-component-ld/Cargo.toml @@ -10,4 +10,4 @@ name = "wasm-component-ld" path = "src/main.rs" [dependencies] -wasm-component-ld = "0.5.13" +wasm-component-ld = "0.5.14" diff --git a/src/version b/src/version index 636ea711ad96..82e24bf241e5 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.89.0 +1.90.0 diff --git a/tests/assembly/cmse.rs b/tests/assembly/cmse.rs index 2984df92225c..a68ee99eac67 100644 --- a/tests/assembly/cmse.rs +++ b/tests/assembly/cmse.rs @@ -6,7 +6,7 @@ //@ [hard] needs-llvm-components: arm //@ [soft] needs-llvm-components: arm #![crate_type = "lib"] -#![feature(abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items)] +#![feature(abi_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items)] #![no_core] extern crate minicore; @@ -53,7 +53,7 @@ use minicore::*; // Branch back to non-secure side // CHECK: bxns lr #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn entry_point() -> i64 { +pub extern "cmse-nonsecure-entry" fn entry_point() -> i64 { 0 } @@ -95,8 +95,6 @@ pub extern "C-cmse-nonsecure-entry" fn entry_point() -> i64 { // Call to non-secure // CHECK: blxns r12 #[no_mangle] -pub fn call_nonsecure( - f: unsafe extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u64, -) -> u64 { +pub fn call_nonsecure(f: unsafe extern "cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u64) -> u64 { unsafe { f(0, 1, 2, 3) } } diff --git a/tests/assembly/naked-functions/wasm32.rs b/tests/assembly/naked-functions/wasm32.rs index 984152f2b453..5f114246ad55 100644 --- a/tests/assembly/naked-functions/wasm32.rs +++ b/tests/assembly/naked-functions/wasm32.rs @@ -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") } diff --git a/tests/assembly/s390x-backchain-toggle.rs b/tests/assembly/s390x-backchain-toggle.rs index 83c7b82d0d4b..9bae15b7d11b 100644 --- a/tests/assembly/s390x-backchain-toggle.rs +++ b/tests/assembly/s390x-backchain-toggle.rs @@ -1,5 +1,5 @@ //@ add-core-stubs -//@ revisions: enable-backchain disable-backchain +//@ revisions: enable-backchain disable-backchain default-backchain //@ assembly-output: emit-asm //@ compile-flags: -Copt-level=3 --crate-type=lib --target=s390x-unknown-linux-gnu //@ needs-llvm-components: systemz @@ -26,6 +26,8 @@ extern "C" fn test_backchain() -> i32 { // enable-backchain: stg [[REG1]], 0(%r15) // disable-backchain: aghi %r15, -160 // disable-backchain-NOT: stg %r{{.*}}, 0(%r15) + // default-backchain: aghi %r15, -160 + // default-backchain-NOT: stg %r{{.*}}, 0(%r15) unsafe { extern_func(); } @@ -35,6 +37,7 @@ extern "C" fn test_backchain() -> i32 { // Make sure that the expected return value is written into %r2 (return register): // enable-backchain-NEXT: lghi %r2, 1 // disable-backchain: lghi %r2, 0 + // default-backchain: lghi %r2, 0 #[cfg(target_feature = "backchain")] { 1 diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index db11549382fc..3e9841b179cb 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -16,6 +16,7 @@ #![feature( no_core, + intrinsics, lang_items, auto_traits, freeze_impls, @@ -196,3 +197,9 @@ impl<'a, 'b: 'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<&'a trait Drop { fn drop(&mut self); } + +pub mod mem { + #[rustc_nounwind] + #[rustc_intrinsic] + pub unsafe fn transmute(src: Src) -> Dst; +} diff --git a/tests/codegen-units/item-collection/drop-glue-noop.rs b/tests/codegen-units/item-collection/drop-glue-noop.rs new file mode 100644 index 000000000000..604ba883bb28 --- /dev/null +++ b/tests/codegen-units/item-collection/drop-glue-noop.rs @@ -0,0 +1,23 @@ +//@ compile-flags:-Clink-dead-code -Zmir-opt-level=0 + +#![deny(dead_code)] +#![crate_type = "lib"] + +//~ MONO_ITEM fn start +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { + // No item produced for this, it's a no-op drop and so is removed. + unsafe { + std::ptr::drop_in_place::(&mut 0); + } + + // No choice but to codegen for indirect drop as a function pointer, since we have to produce a + // function with the right signature. In vtables we can avoid that (tested in + // instantiation-through-vtable.rs) because we special case null pointer for drop glue since + // #122662. + // + //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(None) @@ drop_glue_noop-cgu.0[External] + std::ptr::drop_in_place:: as unsafe fn(*mut u64); + + 0 +} diff --git a/tests/codegen-units/item-collection/instantiation-through-vtable.rs b/tests/codegen-units/item-collection/instantiation-through-vtable.rs index 8f13fd558083..7882a526b682 100644 --- a/tests/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/tests/codegen-units/item-collection/instantiation-through-vtable.rs @@ -24,7 +24,6 @@ impl Trait for Struct { pub fn start(_: isize, _: *const *const u8) -> isize { let s1 = Struct { _a: 0u32 }; - //~ MONO_ITEM fn std::ptr::drop_in_place::> - shim(None) @@ instantiation_through_vtable-cgu.0[External] //~ MONO_ITEM fn as Trait>::foo //~ MONO_ITEM fn as Trait>::bar let r1 = &s1 as &Trait; @@ -32,7 +31,6 @@ pub fn start(_: isize, _: *const *const u8) -> isize { r1.bar(); let s1 = Struct { _a: 0u64 }; - //~ MONO_ITEM fn std::ptr::drop_in_place::> - shim(None) @@ instantiation_through_vtable-cgu.0[External] //~ MONO_ITEM fn as Trait>::foo //~ MONO_ITEM fn as Trait>::bar let _ = &s1 as &Trait; diff --git a/tests/codegen-units/item-collection/non-generic-closures.rs b/tests/codegen-units/item-collection/non-generic-closures.rs index 124fe7e3b69a..2d9c461e6fd2 100644 --- a/tests/codegen-units/item-collection/non-generic-closures.rs +++ b/tests/codegen-units/item-collection/non-generic-closures.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Clink-dead-code -Zinline-mir=no +//@ compile-flags:-Clink-dead-code -Zinline-mir=no -O #![deny(dead_code)] #![crate_type = "lib"] @@ -22,9 +22,8 @@ fn assigned_to_variable_but_not_executed() { //~ MONO_ITEM fn assigned_to_variable_executed_indirectly @@ non_generic_closures-cgu.0[External] fn assigned_to_variable_executed_indirectly() { //~ MONO_ITEM fn assigned_to_variable_executed_indirectly::{closure#0} @@ non_generic_closures-cgu.0[External] - //~ MONO_ITEM fn <{closure@TEST_PATH:28:13: 28:21} as std::ops::FnOnce<(i32,)>>::call_once - shim @@ non_generic_closures-cgu.0[External] - //~ MONO_ITEM fn <{closure@TEST_PATH:28:13: 28:21} as std::ops::FnOnce<(i32,)>>::call_once - shim(vtable) @@ non_generic_closures-cgu.0[External] - //~ MONO_ITEM fn std::ptr::drop_in_place::<{closure@TEST_PATH:28:13: 28:21}> - shim(None) @@ non_generic_closures-cgu.0[External] + //~ MONO_ITEM fn <{closure@TEST_PATH:27:13: 27:21} as std::ops::FnOnce<(i32,)>>::call_once - shim @@ non_generic_closures-cgu.0[External] + //~ MONO_ITEM fn <{closure@TEST_PATH:27:13: 27:21} as std::ops::FnOnce<(i32,)>>::call_once - shim(vtable) @@ non_generic_closures-cgu.0[External] let f = |a: i32| { let _ = a + 2; }; @@ -40,6 +39,20 @@ fn assigned_to_variable_executed_directly() { f(4); } +// Make sure we generate mono items for stateful closures that need dropping +//~ MONO_ITEM fn with_drop @@ non_generic_closures-cgu.0[External] +fn with_drop(v: PresentDrop) { + //~ MONO_ITEM fn with_drop::{closure#0} @@ non_generic_closures-cgu.0[External] + //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(Some(PresentDrop)) @@ non_generic_closures-cgu.0[Internal] + //~ MONO_ITEM fn std::ptr::drop_in_place::<{closure@TEST_PATH:49:14: 49:24}> - shim(Some({closure@TEST_PATH:49:14: 49:24})) @@ non_generic_closures-cgu.0[Internal] + + let _f = |a: usize| { + let _ = a + 2; + //~ MONO_ITEM fn std::mem::drop:: @@ non_generic_closures-cgu.0[External] + drop(v); + }; +} + //~ MONO_ITEM fn start @@ non_generic_closures-cgu.0[External] #[no_mangle] pub fn start(_: isize, _: *const *const u8) -> isize { @@ -47,6 +60,7 @@ pub fn start(_: isize, _: *const *const u8) -> isize { assigned_to_variable_but_not_executed(); assigned_to_variable_executed_directly(); assigned_to_variable_executed_indirectly(); + with_drop(PresentDrop); 0 } @@ -55,3 +69,10 @@ pub fn start(_: isize, _: *const *const u8) -> isize { fn run_closure(f: &Fn(i32)) { f(3); } + +struct PresentDrop; + +impl Drop for PresentDrop { + //~ MONO_ITEM fn ::drop @@ non_generic_closures-cgu.0[External] + fn drop(&mut self) {} +} diff --git a/tests/codegen-units/item-collection/unsizing.rs b/tests/codegen-units/item-collection/unsizing.rs index 15e42bce2495..b751d2153a94 100644 --- a/tests/codegen-units/item-collection/unsizing.rs +++ b/tests/codegen-units/item-collection/unsizing.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Zmir-opt-level=0 +//@ compile-flags:-Zmir-opt-level=0 -O #![deny(dead_code)] #![feature(coerce_unsized)] @@ -42,33 +42,47 @@ struct Wrapper(#[allow(dead_code)] *const T); impl, U: ?Sized> CoerceUnsized> for Wrapper {} +struct PresentDrop; + +impl Drop for PresentDrop { + fn drop(&mut self) {} +} + +// Custom Coercion Case +impl Trait for PresentDrop { + fn foo(&self) {} +} + //~ MONO_ITEM fn start #[no_mangle] pub fn start(_: isize, _: *const *const u8) -> isize { // simple case let bool_sized = &true; - //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(None) @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn ::foo let _bool_unsized = bool_sized as &Trait; let char_sized = &'a'; - //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(None) @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn ::foo let _char_unsized = char_sized as &Trait; // struct field let struct_sized = &Struct { _a: 1, _b: 2, _c: 3.0f64 }; - //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(None) @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn ::foo let _struct_unsized = struct_sized as &Struct; // custom coercion let wrapper_sized = Wrapper(&0u32); - //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(None) @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn ::foo let _wrapper_sized = wrapper_sized as Wrapper; + // with drop + let droppable = &PresentDrop; + //~ MONO_ITEM fn ::drop @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(Some(PresentDrop)) @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn ::foo + let droppable = droppable as &dyn Trait; + false.foo(); 0 diff --git a/tests/codegen/abi-x86-interrupt.rs b/tests/codegen/abi-x86-interrupt.rs index 255ccba2c111..9a1ded2c9e37 100644 --- a/tests/codegen/abi-x86-interrupt.rs +++ b/tests/codegen/abi-x86-interrupt.rs @@ -13,8 +13,6 @@ extern crate minicore; use minicore::*; -// CHECK: define x86_intrcc i64 @has_x86_interrupt_abi +// CHECK: define x86_intrcc void @has_x86_interrupt_abi #[no_mangle] -pub extern "x86-interrupt" fn has_x86_interrupt_abi(a: i64) -> i64 { - a -} +pub extern "x86-interrupt" fn has_x86_interrupt_abi() {} diff --git a/tests/codegen/align-fn.rs b/tests/codegen/align-fn.rs index 660d8cd2bbf4..267da0602406 100644 --- a/tests/codegen/align-fn.rs +++ b/tests/codegen/align-fn.rs @@ -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() {} diff --git a/tests/codegen/asm/critical.rs b/tests/codegen/asm/critical.rs index 8c039900cab3..0f29d7c69b46 100644 --- a/tests/codegen/asm/critical.rs +++ b/tests/codegen/asm/critical.rs @@ -1,6 +1,5 @@ //@ only-x86_64 //@ compile-flags: -C no-prepopulate-passes -#![feature(asm_goto)] #![feature(asm_goto_with_outputs)] #![crate_type = "lib"] use std::arch::asm; diff --git a/tests/codegen/min-function-alignment.rs b/tests/codegen/min-function-alignment.rs index 7c0ad12402aa..78989ec5df23 100644 --- a/tests/codegen/min-function-alignment.rs +++ b/tests/codegen/min-function-alignment.rs @@ -1,33 +1,35 @@ //@ revisions: align16 align1024 -//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 +//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 -Clink-dead-code //@ [align16] compile-flags: -Zmin-function-alignment=16 //@ [align1024] compile-flags: -Zmin-function-alignment=1024 #![crate_type = "lib"] #![feature(fn_align)] -// functions without explicit alignment use the global minimum +// Functions without explicit alignment use the global minimum. // -// CHECK-LABEL: @no_explicit_align +// NOTE: this function deliberately has zero (0) attributes! That is to make sure that +// `-Zmin-function-alignment` is applied regardless of whether attributes are used. +// +// CHECK-LABEL: no_explicit_align // align16: align 16 // align1024: align 1024 -#[no_mangle] pub fn no_explicit_align() {} // CHECK-LABEL: @lower_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 diff --git a/tests/codegen/naked-asan.rs b/tests/codegen/naked-asan.rs index 223c41b15bb3..46218cf79d6d 100644 --- a/tests/codegen/naked-asan.rs +++ b/tests/codegen/naked-asan.rs @@ -1,22 +1,28 @@ +//@ add-core-stubs +//@ needs-llvm-components: x86 +//@ compile-flags: --target x86_64-unknown-linux-gnu -Zsanitizer=address -Ctarget-feature=-crt-static + // Make sure we do not request sanitizers for naked functions. -//@ only-x86_64 -//@ needs-sanitizer-address -//@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static - #![crate_type = "lib"] +#![feature(no_core)] #![no_std] +#![no_core] #![feature(abi_x86_interrupt)] +extern crate minicore; +use minicore::*; + +#[no_mangle] pub fn caller() { - page_fault_handler(1, 2); + unsafe { asm!("call {}", sym page_fault_handler) } } -// CHECK: declare x86_intrcc void @page_fault_handler(ptr {{.*}}, i64{{.*}}){{.*}}#[[ATTRS:[0-9]+]] +// CHECK: declare x86_intrcc void @page_fault_handler(){{.*}}#[[ATTRS:[0-9]+]] #[unsafe(naked)] #[no_mangle] -pub extern "x86-interrupt" fn page_fault_handler(_: u64, _: u64) { - core::arch::naked_asm!("ud2") +pub extern "x86-interrupt" fn page_fault_handler() { + naked_asm!("ud2") } // CHECK: #[[ATTRS]] = diff --git a/tests/codegen/naked-fn/aligned.rs b/tests/codegen/naked-fn/aligned.rs index 47ef779f1b21..f9fce8e5a5d5 100644 --- a/tests/codegen/naked-fn/aligned.rs +++ b/tests/codegen/naked-fn/aligned.rs @@ -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() { diff --git a/tests/codegen/naked-fn/min-function-alignment.rs b/tests/codegen/naked-fn/min-function-alignment.rs index 1d778be8c90d..59554c1cae55 100644 --- a/tests/codegen/naked-fn/min-function-alignment.rs +++ b/tests/codegen/naked-fn/min-function-alignment.rs @@ -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") diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs index 2a7eca6fc196..8fec275fd064 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs @@ -1,5 +1,9 @@ // Verifies that type metadata identifiers for drop functions are emitted correctly. // +// Non needs_drop drop glue isn't codegen'd at all, so we don't try to check the IDs there. But we +// do check it's not emitted which should help catch bugs if we do start generating it again in the +// future. +// //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static @@ -10,18 +14,18 @@ // CHECK: call i1 @llvm.type.test(ptr {{%.+}}, metadata !"_ZTSFvPu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops4drop4Dropu6regionEE") struct EmptyDrop; -// CHECK: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}EmptyDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +// CHECK-NOT: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}EmptyDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -struct NonEmptyDrop; +struct PresentDrop; -impl Drop for NonEmptyDrop { +impl Drop for PresentDrop { fn drop(&mut self) {} - // CHECK: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}NonEmptyDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} + // CHECK: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}PresentDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} } pub fn foo() { let _ = Box::new(EmptyDrop) as Box; - let _ = Box::new(NonEmptyDrop) as Box; + let _ = Box::new(PresentDrop) as Box; } // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvPu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops4drop4Dropu6regionEE"} diff --git a/tests/codegen/target-feature-negative-implication.rs b/tests/codegen/target-feature-negative-implication.rs new file mode 100644 index 000000000000..36cd82dd8cf5 --- /dev/null +++ b/tests/codegen/target-feature-negative-implication.rs @@ -0,0 +1,20 @@ +//@ add-core-stubs +//@ needs-llvm-components: x86 +//@ compile-flags: --target=x86_64-unknown-linux-gnu +//@ compile-flags: -Ctarget-feature=-avx2 + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +extern crate minicore; +use minicore::*; + +#[no_mangle] +pub unsafe fn banana() { + // CHECK-LABEL: @banana() + // CHECK-SAME: [[BANANAATTRS:#[0-9]+]] { +} + +// CHECK: attributes [[BANANAATTRS]] +// CHECK-SAME: -avx512 diff --git a/tests/codegen/target-feature-overrides.rs b/tests/codegen/target-feature-overrides.rs index 0fc1e0136b3f..eb19b0de2fa8 100644 --- a/tests/codegen/target-feature-overrides.rs +++ b/tests/codegen/target-feature-overrides.rs @@ -1,3 +1,4 @@ +// ignore-tidy-linelength //@ add-core-stubs //@ revisions: COMPAT INCOMPAT //@ needs-llvm-components: x86 @@ -39,7 +40,7 @@ pub unsafe fn banana() -> u32 { // CHECK: attributes [[APPLEATTRS]] // COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}" -// INCOMPAT-SAME: "target-features"="-avx2,-avx,+avx,{{.*}}" +// INCOMPAT-SAME: "target-features"="{{(-[^,]+,)*}}-avx2{{(,-[^,]+)*}},-avx{{(,-[^,]+)*}},+avx{{(,\+[^,]+)*}}" // CHECK: attributes [[BANANAATTRS]] // COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}" -// INCOMPAT-SAME: "target-features"="-avx2,-avx" +// INCOMPAT-SAME: "target-features"="{{(-[^,]+,)*}}-avx2{{(,-[^,]+)*}},-avx{{(,-[^,]+)*}}" diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 6be0e21e0ef3..81499c070d19 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -4,14 +4,23 @@ //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 +// Rust made SVE require neon. //@ [ENABLE_SVE] compile-flags: -C target-feature=+sve -Copt-level=0 -// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } +// ENABLE_SVE: attributes #0 +// ENABLE_SVE-SAME: +neon +// ENABLE_SVE-SAME: +sve +// However, disabling SVE does not disable neon. //@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0 -// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(-sve,?)|(\+neon,?))*}}" } +// DISABLE_SVE: attributes #0 +// DISABLE_SVE-NOT: -neon +// DISABLE_SVE-SAME: -sve +// OTOH, neon fn `fp-armv8` are fully tied; toggling neon must toggle `fp-armv8` the same way. //@ [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 -// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(-fp-armv8,?)|(-neon,?))*}}" } +// DISABLE_NEON: attributes #0 +// DISABLE_NEON-SAME: -neon +// DISABLE_NEON-SAME: -fp-armv8 //@ [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 // ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fp-armv8,?)|(\+neon,?))*}}" } diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs index c080259a9172..c57ade58c30e 100644 --- a/tests/codegen/transmute-scalar.rs +++ b/tests/codegen/transmute-scalar.rs @@ -55,3 +55,48 @@ pub fn ptr_to_int(p: *mut u16) -> usize { pub fn int_to_ptr(i: usize) -> *mut u16 { unsafe { std::mem::transmute(i) } } + +// This is the one case where signedness matters to transmuting: +// the LLVM type is `i8` here because of `repr(i8)`, +// whereas below with the `repr(u8)` it's `i1` in LLVM instead. +#[repr(i8)] +pub enum FakeBoolSigned { + False = 0, + True = 1, +} + +// CHECK-LABEL: define{{.*}}i8 @bool_to_fake_bool_signed(i1 zeroext %b) +// CHECK: %_0 = zext i1 %b to i8 +// CHECK-NEXT: ret i8 %_0 +#[no_mangle] +pub fn bool_to_fake_bool_signed(b: bool) -> FakeBoolSigned { + unsafe { std::mem::transmute(b) } +} + +// CHECK-LABEL: define{{.*}}i1 @fake_bool_signed_to_bool(i8 %b) +// CHECK: %_0 = trunc nuw i8 %b to i1 +// CHECK-NEXT: ret i1 %_0 +#[no_mangle] +pub fn fake_bool_signed_to_bool(b: FakeBoolSigned) -> bool { + unsafe { std::mem::transmute(b) } +} + +#[repr(u8)] +pub enum FakeBoolUnsigned { + False = 0, + True = 1, +} + +// CHECK-LABEL: define{{.*}}i1 @bool_to_fake_bool_unsigned(i1 zeroext %b) +// CHECK: ret i1 %b +#[no_mangle] +pub fn bool_to_fake_bool_unsigned(b: bool) -> FakeBoolUnsigned { + unsafe { std::mem::transmute(b) } +} + +// CHECK-LABEL: define{{.*}}i1 @fake_bool_unsigned_to_bool(i1 zeroext %b) +// CHECK: ret i1 %b +#[no_mangle] +pub fn fake_bool_unsigned_to_bool(b: FakeBoolUnsigned) -> bool { + unsafe { std::mem::transmute(b) } +} diff --git a/tests/crashes/126269.rs b/tests/crashes/126269.rs deleted file mode 100644 index ca4b76eb930d..000000000000 --- a/tests/crashes/126269.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: rust-lang/rust#126269 -#![feature(coerce_unsized)] - -pub enum Foo { - Bar([T; usize::MAX]), -} - -use std::ops::CoerceUnsized; - -impl CoerceUnsized for T {} - -fn main() {} diff --git a/tests/crashes/126982.rs b/tests/crashes/126982.rs deleted file mode 100644 index 8522d9415eb8..000000000000 --- a/tests/crashes/126982.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: rust-lang/rust#126982 - -#![feature(coerce_unsized)] -use std::ops::CoerceUnsized; - -struct Foo { - a: T, -} - -impl CoerceUnsized for Foo {} - -union U { - a: usize, -} - -const C: U = Foo { a: 10 }; - -fn main() {} diff --git a/tests/crashes/130104.rs b/tests/crashes/130104.rs index 0ffc21ad3604..b961108c9233 100644 --- a/tests/crashes/130104.rs +++ b/tests/crashes/130104.rs @@ -2,5 +2,5 @@ fn main() { let non_secure_function = - core::mem::transmute:: _, extern "C-cmse-nonsecure-call" fn() -> _>; + core::mem::transmute:: _, extern "cmse-nonsecure-call" fn() -> _>; } diff --git a/tests/crashes/131048.rs b/tests/crashes/131048.rs deleted file mode 100644 index d57e9921a8ab..000000000000 --- a/tests/crashes/131048.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #131048 - -impl std::ops::CoerceUnsized for A {} - -fn main() { - format_args!("Hello, world!"); -} diff --git a/tests/crashes/132142.rs b/tests/crashes/132142.rs index 9a026f3bca71..813bf0bf0a8e 100644 --- a/tests/crashes/132142.rs +++ b/tests/crashes/132142.rs @@ -1,3 +1,3 @@ //@ known-bug: #132142 -async extern "C-cmse-nonsecure-entry" fn fun(...) {} +async extern "cmse-nonsecure-entry" fn fun(...) {} diff --git a/tests/crashes/132430.rs b/tests/crashes/132430.rs deleted file mode 100644 index 81c8c6d6f7d3..000000000000 --- a/tests/crashes/132430.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #132430 - -//@ compile-flags: --crate-type=lib -//@ edition: 2018 -#![feature(cmse_nonsecure_entry)] -struct Test; - -impl Test { - pub async unsafe extern "C-cmse-nonsecure-entry" fn test(val: &str) {} -} diff --git a/tests/crashes/134217.rs b/tests/crashes/134217.rs deleted file mode 100644 index 1b14c660e8b4..000000000000 --- a/tests/crashes/134217.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #134217 - -impl std::ops::CoerceUnsized for A {} - -fn main() { - if let _ = true - && true - {} -} diff --git a/tests/crashes/136678.rs b/tests/crashes/136678.rs deleted file mode 100644 index e7d7de23bfeb..000000000000 --- a/tests/crashes/136678.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: #136678 -#![feature(inherent_associated_types)] -#![feature(generic_const_exprs)] -#![allow(incomplete_features)] - -struct B; - -struct Test; - -impl Test { - type B = B<{ A }>; - - fn test(a: Self::B) -> Self::B { - a - } -} - -pub fn main() {} diff --git a/tests/crashes/138131.rs b/tests/crashes/138131.rs deleted file mode 100644 index f400c02de8d6..000000000000 --- a/tests/crashes/138131.rs +++ /dev/null @@ -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() {} diff --git a/tests/crashes/138265.rs b/tests/crashes/138265.rs deleted file mode 100644 index f6c8ea748895..000000000000 --- a/tests/crashes/138265.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #138265 - -#![feature(coerce_unsized)] -#![crate_type = "lib"] -impl std::ops::CoerceUnsized for A {} -pub fn f() { - [0; { - let mut c = &0; - c = &0; - 0 - }] -} diff --git a/tests/crashes/138738.rs b/tests/crashes/138738.rs deleted file mode 100644 index 74e5effa56f5..000000000000 --- a/tests/crashes/138738.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #138738 -//@ only-x86_64 - -#![feature(abi_ptx)] -fn main() { - let a = unsafe { core::mem::transmute::(4) }(2); -} diff --git a/tests/incremental/issue-61323.rs b/tests/incremental/issue-61323.rs index b7423c81fc16..4845648d49c8 100644 --- a/tests/incremental/issue-61323.rs +++ b/tests/incremental/issue-61323.rs @@ -1,7 +1,7 @@ //@ revisions: rpass cfail enum A { - //[cfail]~^ ERROR 3:1: 3:7: recursive types `A` and `C` have infinite size [E0072] + //[cfail]~^ ERROR recursive types `A` and `C` have infinite size [E0072] B(C), } diff --git a/tests/incremental/track-deps-in-new-solver.rs b/tests/incremental/track-deps-in-new-solver.rs index fb013b2b24a7..51cd6b89e37e 100644 --- a/tests/incremental/track-deps-in-new-solver.rs +++ b/tests/incremental/track-deps-in-new-solver.rs @@ -3,6 +3,8 @@ //@ compile-flags: -Znext-solver //@ check-pass +#![allow(dead_code)] + pub trait Future { type Error; fn poll() -> Self::Error; diff --git a/tests/mir-opt/copy-prop/write_to_borrowed.main.CopyProp.diff b/tests/mir-opt/copy-prop/write_to_borrowed.main.CopyProp.diff new file mode 100644 index 000000000000..eab06b1ba1e7 --- /dev/null +++ b/tests/mir-opt/copy-prop/write_to_borrowed.main.CopyProp.diff @@ -0,0 +1,30 @@ +- // MIR for `main` before CopyProp ++ // MIR for `main` after CopyProp + + fn main() -> () { + let mut _0: (); + let mut _1: *const char; + let mut _2: char; + let mut _3: char; + let mut _4: char; + let mut _5: char; + let mut _6: &char; + let mut _7: (); + + bb0: { + _1 = &raw const _2; + _3 = const 'b'; + _5 = copy _3; + _6 = &_3; +- _4 = copy _5; + (*_1) = copy (*_6); + _6 = &_5; +- _7 = dump_var::(copy _4) -> [return: bb1, unwind unreachable]; ++ _7 = dump_var::(copy _5) -> [return: bb1, unwind unreachable]; + } + + bb1: { + return; + } + } + diff --git a/tests/mir-opt/copy-prop/write_to_borrowed.rs b/tests/mir-opt/copy-prop/write_to_borrowed.rs new file mode 100644 index 000000000000..58809749103e --- /dev/null +++ b/tests/mir-opt/copy-prop/write_to_borrowed.rs @@ -0,0 +1,45 @@ +//@ test-mir-pass: CopyProp + +#![feature(custom_mir, core_intrinsics)] +#![allow(internal_features)] + +use std::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime")] +fn main() { + mir! { + // Both _3 and _5 are borrowed, check that we do not unify them, and that we do not + // introduce a write to any of them. + let _1; + let _2; + let _3; + let _4; + let _5; + let _6; + let _7; + // CHECK: bb0: { + { + // CHECK-NEXT: _1 = &raw const _2; + _1 = core::ptr::addr_of!(_2); + // CHECK-NEXT: _3 = const 'b'; + _3 = 'b'; + // CHECK-NEXT: _5 = copy _3; + _5 = _3; + // CHECK-NEXT: _6 = &_3; + _6 = &_3; + // CHECK-NOT: {{_.*}} = {{_.*}}; + _4 = _5; + // CHECK-NEXT: (*_1) = copy (*_6); + *_1 = *_6; + // CHECK-NEXT: _6 = &_5; + _6 = &_5; + // CHECK-NEXT: _7 = dump_var::(copy _5) + Call(_7 = dump_var(_4), ReturnTo(bb1), UnwindUnreachable()) + } + bb1 = { Return() } + } +} + +fn dump_var(_: T) {} + +// EMIT_MIR write_to_borrowed.main.CopyProp.diff diff --git a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff index 33f1ad9bef4e..e2d3c6c41b89 100644 --- a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff @@ -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; + let mut _14: &u32; + let mut _16: core::fmt::rt::Argument<'_>; + let mut _17: &std::boxed::Box; let mut _18: core::fmt::rt::Argument<'_>; - let mut _19: &std::boxed::Box; - let _20: &std::boxed::Box; - 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, ::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; + 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, ::Err>; ++ let _33: u32; scope 1 { - debug foo => _1; -+ debug ((foo: Foo).0: std::result::Result, ::Err>) => _29; -+ debug ((foo: Foo).1: u32) => _30; ++ debug ((foo: Foo).0: std::result::Result, ::Err>) => _32; ++ debug ((foo: Foo).1: u32) => _33; let _5: std::result::Result, ::Err>; scope 2 { debug x => _5; @@ -42,17 +43,29 @@ scope 4 { debug x => _8; let _8: std::boxed::Box; - let mut _24: &[&str; 3]; + let _12: (&std::boxed::Box, &u32); ++ let _34: &std::boxed::Box; ++ let _35: &u32; + scope 5 { +- debug args => _12; ++ debug ((args: (&Box, &u32)).0: &std::boxed::Box) => _34; ++ debug ((args: (&Box, &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::, ::Err>::Ok(move _3); StorageDead(_3); - _1 = Foo:: { 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, ::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); StorageLive(_9); StorageLive(_10); StorageLive(_11); - StorageLive(_12); +- StorageLive(_12); ++ StorageLive(_34); ++ StorageLive(_35); ++ nop; StorageLive(_13); - _24 = const foo::::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::>(move _19) -> [return: bb3, unwind unreachable]; +- _26 = deref_copy (_12.0: &std::boxed::Box); ++ _26 = deref_copy _34; + _17 = &(*_26); + _16 = core::fmt::rt::Argument::<'_>::new_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::(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::(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::>::new_v1::<3, 2>(move _12, move _15) -> [return: bb5, unwind unreachable]; + StorageDead(_16); + StorageLive(_20); + StorageLive(_21); + _25 = const foo::::promoted[0]; + _21 = &(*_25); + _20 = &(*_21); + StorageLive(_23); + StorageLive(_24); + _24 = &_15; + _23 = &(*_24); + _11 = core::fmt::rt::>::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: { diff --git a/tests/pretty/pin-ergonomics-hir.pp b/tests/pretty/pin-ergonomics-hir.pp new file mode 100644 index 000000000000..212e0e174dae --- /dev/null +++ b/tests/pretty/pin-ergonomics-hir.pp @@ -0,0 +1,44 @@ +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:pin-ergonomics-hir.pp + +#![feature(pin_ergonomics)] +#![allow(dead_code, incomplete_features)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +use std::pin::Pin; + +struct Foo; + +impl Foo { + fn baz(&mut self) { } + + fn baz_const(&self) { } + + fn baz_lt<'a>(&mut self) { } + + fn baz_const_lt(&self) { } +} + +fn foo(_: Pin<&'_ mut Foo>) { } +fn foo_lt<'a>(_: Pin<&'a mut Foo>) { } + +fn foo_const(_: Pin<&'_ Foo>) { } +fn foo_const_lt(_: Pin<&'_ Foo>) { } + +fn bar() { + let mut x: Pin<&mut _> = &pin mut Foo; + foo(x.as_mut()); + foo(x.as_mut()); + foo_const(x); + + let x: Pin<&_> = &pin const Foo; + + foo_const(x); + foo_const(x); +} + +fn main() { } diff --git a/tests/pretty/pin-ergonomics-hir.rs b/tests/pretty/pin-ergonomics-hir.rs new file mode 100644 index 000000000000..5f2158258f07 --- /dev/null +++ b/tests/pretty/pin-ergonomics-hir.rs @@ -0,0 +1,40 @@ +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:pin-ergonomics-hir.pp + +#![feature(pin_ergonomics)] +#![allow(dead_code, incomplete_features)] + +use std::pin::Pin; + +struct Foo; + +impl Foo { + fn baz(&mut self) { } + + fn baz_const(&self) { } + + fn baz_lt<'a>(&mut self) { } + + fn baz_const_lt(&self) { } +} + +fn foo(_: Pin<&'_ mut Foo>) { } +fn foo_lt<'a>(_: Pin<&'a mut Foo>) { } + +fn foo_const(_: Pin<&'_ Foo>) { } +fn foo_const_lt(_: Pin<&'_ Foo>) { } + +fn bar() { + let mut x: Pin<&mut _> = &pin mut Foo; + foo(x.as_mut()); + foo(x.as_mut()); + foo_const(x); + + let x: Pin<&_> = &pin const Foo; + + foo_const(x); + foo_const(x); +} + +fn main() { } diff --git a/tests/pretty/pin-ergonomics.rs b/tests/pretty/pin-ergonomics.rs index 47ffc97b1183..8e8ced791b13 100644 --- a/tests/pretty/pin-ergonomics.rs +++ b/tests/pretty/pin-ergonomics.rs @@ -3,6 +3,8 @@ #![feature(pin_ergonomics)] #![allow(dead_code, incomplete_features)] +use std::pin::Pin; + struct Foo; impl Foo { @@ -21,4 +23,15 @@ fn foo_lt<'a>(_: &'a pin mut Foo) {} fn foo_const(_: &pin const Foo) {} fn foo_const_lt(_: &'_ pin const Foo) {} +fn bar() { + let mut x: Pin<&mut _> = &pin mut Foo; + foo(x.as_mut()); + foo(x.as_mut()); + foo_const(x); + + let x: Pin<&_> = &pin const Foo; + foo_const(x); + foo_const(x); +} + fn main() {} diff --git a/tests/run-make/allow-warnings-cmdline-stability/rmake.rs b/tests/run-make/allow-warnings-cmdline-stability/rmake.rs index 66ca3eb3383b..033a06741e22 100644 --- a/tests/run-make/allow-warnings-cmdline-stability/rmake.rs +++ b/tests/run-make/allow-warnings-cmdline-stability/rmake.rs @@ -1,4 +1,4 @@ -//@ needs-target-std +//@ ignore-cross-compile // Test that `-Awarnings` suppresses warnings for unstable APIs. use run_make_support::rustc; diff --git a/tests/run-make/apple-deployment-target/rmake.rs b/tests/run-make/apple-deployment-target/rmake.rs index 839e21b7496d..7297a8622240 100644 --- a/tests/run-make/apple-deployment-target/rmake.rs +++ b/tests/run-make/apple-deployment-target/rmake.rs @@ -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"); diff --git a/tests/run-make/apple-sdk-version/rmake.rs b/tests/run-make/apple-sdk-version/rmake.rs index 43e805772043..1f4f0ab8aef8 100644 --- a/tests/run-make/apple-sdk-version/rmake.rs +++ b/tests/run-make/apple-sdk-version/rmake.rs @@ -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") diff --git a/tests/run-make/arm64ec-import-export-static/export.rs b/tests/run-make/arm64ec-import-export-static/export.rs new file mode 100644 index 000000000000..ca6ccf00ca17 --- /dev/null +++ b/tests/run-make/arm64ec-import-export-static/export.rs @@ -0,0 +1,27 @@ +#![crate_type = "dylib"] +#![allow(internal_features)] +#![feature(no_core, lang_items)] +#![no_core] +#![no_std] + +// This is needed because of #![no_core]: +#[lang = "pointee_sized"] +pub trait PointeeSized {} +#[lang = "meta_sized"] +pub trait MetaSized: PointeeSized {} +#[lang = "sized"] +pub trait Sized: MetaSized {} +#[lang = "sync"] +trait Sync {} +impl Sync for i32 {} +#[lang = "copy"] +pub trait Copy {} +impl Copy for i32 {} +#[lang = "drop_in_place"] +pub unsafe fn drop_in_place(_: *mut T) {} +#[no_mangle] +extern "system" fn _DllMainCRTStartup(_: *const u8, _: u32, _: *const u8) -> u32 { + 1 +} + +pub static VALUE: i32 = 42; diff --git a/tests/run-make/arm64ec-import-export-static/import.rs b/tests/run-make/arm64ec-import-export-static/import.rs new file mode 100644 index 000000000000..9d52db251250 --- /dev/null +++ b/tests/run-make/arm64ec-import-export-static/import.rs @@ -0,0 +1,12 @@ +#![crate_type = "cdylib"] +#![allow(internal_features)] +#![feature(no_core)] +#![no_std] +#![no_core] + +extern crate export; + +#[no_mangle] +pub extern "C" fn func() -> i32 { + export::VALUE +} diff --git a/tests/run-make/arm64ec-import-export-static/rmake.rs b/tests/run-make/arm64ec-import-export-static/rmake.rs new file mode 100644 index 000000000000..7fa31144810d --- /dev/null +++ b/tests/run-make/arm64ec-import-export-static/rmake.rs @@ -0,0 +1,15 @@ +// Test that a static can be exported from one crate and imported into another. +// +// This was broken for Arm64EC as only functions, not variables, should be +// decorated with `#`. +// See https://github.com/rust-lang/rust/issues/138541 + +//@ needs-llvm-components: aarch64 +//@ only-windows + +use run_make_support::rustc; + +fn main() { + rustc().input("export.rs").target("aarch64-pc-windows-msvc").panic("abort").run(); + rustc().input("import.rs").target("aarch64-pc-windows-msvc").panic("abort").run(); +} diff --git a/tests/run-make/bin-emit-no-symbols/app.rs b/tests/run-make/bin-emit-no-symbols/app.rs index e9dc1e9744fb..ad74fcc43dce 100644 --- a/tests/run-make/bin-emit-no-symbols/app.rs +++ b/tests/run-make/bin-emit-no-symbols/app.rs @@ -12,7 +12,15 @@ fn panic(_: &PanicInfo) -> ! { } #[lang = "eh_personality"] -fn eh() {} +fn eh( + _version: i32, + _actions: i32, + _exception_class: u64, + _exception_object: *mut (), + _context: *mut (), +) -> i32 { + loop {} +} #[alloc_error_handler] fn oom(_: Layout) -> ! { diff --git a/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs b/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs index 63904bea6227..cca528c42526 100644 --- a/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs +++ b/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs @@ -3,7 +3,9 @@ // prevent the creation of a functional binary. // See https://github.com/rust-lang/rust/pull/49878 -//@ ignore-cross-compile +//@ needs-target-std +//@ ignore-android: FIXME(#142855) +//@ ignore-sgx: (x86 machine code cannot be directly executed) use run_make_support::{cc, extra_c_flags, run, rustc, static_lib_name}; diff --git a/tests/run-make/crate-circular-deps-link/a.rs b/tests/run-make/crate-circular-deps-link/a.rs index a54f429550e7..99b2b65049de 100644 --- a/tests/run-make/crate-circular-deps-link/a.rs +++ b/tests/run-make/crate-circular-deps-link/a.rs @@ -21,6 +21,12 @@ extern "C" fn __rust_foreign_exception() -> ! { } #[lang = "eh_personality"] -fn eh_personality() { +fn eh_personality( + _version: i32, + _actions: i32, + _exception_class: u64, + _exception_object: *mut (), + _context: *mut (), +) -> i32 { loop {} } diff --git a/tests/run-make/crate-circular-deps-link/rmake.rs b/tests/run-make/crate-circular-deps-link/rmake.rs index 6771fdec7e8a..38b922c328f8 100644 --- a/tests/run-make/crate-circular-deps-link/rmake.rs +++ b/tests/run-make/crate-circular-deps-link/rmake.rs @@ -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. // diff --git a/tests/run-make/doctests-merge/rmake.rs b/tests/run-make/doctests-merge/rmake.rs index 8236997d72d7..7893d4988ebb 100644 --- a/tests/run-make/doctests-merge/rmake.rs +++ b/tests/run-make/doctests-merge/rmake.rs @@ -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}; diff --git a/tests/run-make/doctests-runtool/rmake.rs b/tests/run-make/doctests-runtool/rmake.rs index aaba41749102..bc406630932a 100644 --- a/tests/run-make/doctests-runtool/rmake.rs +++ b/tests/run-make/doctests-runtool/rmake.rs @@ -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; diff --git a/tests/run-make/embed-metadata/rmake.rs b/tests/run-make/embed-metadata/rmake.rs index a41716d15429..2de6575feb88 100644 --- a/tests/run-make/embed-metadata/rmake.rs +++ b/tests/run-make/embed-metadata/rmake.rs @@ -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 diff --git a/tests/run-make/embed-source-dwarf/rmake.rs b/tests/run-make/embed-source-dwarf/rmake.rs index 99fad359054b..f57e6aba13ed 100644 --- a/tests/run-make/embed-source-dwarf/rmake.rs +++ b/tests/run-make/embed-source-dwarf/rmake.rs @@ -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 diff --git a/tests/run-make/emit-shared-files/rmake.rs b/tests/run-make/emit-shared-files/rmake.rs index c8c113ce9445..f88fe69aa9cd 100644 --- a/tests/run-make/emit-shared-files/rmake.rs +++ b/tests/run-make/emit-shared-files/rmake.rs @@ -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() { diff --git a/tests/run-make/emit-stack-sizes/rmake.rs b/tests/run-make/emit-stack-sizes/rmake.rs index 886e875cfae8..2e7f40896a5d 100644 --- a/tests/run-make/emit-stack-sizes/rmake.rs +++ b/tests/run-make/emit-stack-sizes/rmake.rs @@ -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. diff --git a/tests/run-make/env-dep-info/rmake.rs b/tests/run-make/env-dep-info/rmake.rs index 97006a632057..18e6250d7d45 100644 --- a/tests/run-make/env-dep-info/rmake.rs +++ b/tests/run-make/env-dep-info/rmake.rs @@ -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 diff --git a/tests/run-make/exit-code/rmake.rs b/tests/run-make/exit-code/rmake.rs index 5fdf920b55a6..21dea06a55af 100644 --- a/tests/run-make/exit-code/rmake.rs +++ b/tests/run-make/exit-code/rmake.rs @@ -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}; diff --git a/tests/run-make/export-executable-symbols/rmake.rs b/tests/run-make/export-executable-symbols/rmake.rs index dc8c59b9c742..884c7362822f 100644 --- a/tests/run-make/export-executable-symbols/rmake.rs +++ b/tests/run-make/export-executable-symbols/rmake.rs @@ -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}; diff --git a/tests/run-make/export/disambiguator/rmake.rs b/tests/run-make/export/disambiguator/rmake.rs index f855e42d08ee..afbe7f2cdbc3 100644 --- a/tests/run-make/export/disambiguator/rmake.rs +++ b/tests/run-make/export/disambiguator/rmake.rs @@ -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() { diff --git a/tests/run-make/export/extern-opt/rmake.rs b/tests/run-make/export/extern-opt/rmake.rs index a2f9ba28c2f5..2e3a70b251c6 100644 --- a/tests/run-make/export/extern-opt/rmake.rs +++ b/tests/run-make/export/extern-opt/rmake.rs @@ -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() { diff --git a/tests/run-make/export/simple/rmake.rs b/tests/run-make/export/simple/rmake.rs index f855e42d08ee..6468e38c69b5 100644 --- a/tests/run-make/export/simple/rmake.rs +++ b/tests/run-make/export/simple/rmake.rs @@ -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() { diff --git a/tests/run-make/extern-diff-internal-name/rmake.rs b/tests/run-make/extern-diff-internal-name/rmake.rs index 1bae8decb052..c905de1d9a8d 100644 --- a/tests/run-make/extern-diff-internal-name/rmake.rs +++ b/tests/run-make/extern-diff-internal-name/rmake.rs @@ -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 diff --git a/tests/run-make/extern-flag-fun/rmake.rs b/tests/run-make/extern-flag-fun/rmake.rs index 181a76b7cfa0..0b5e3c245c55 100644 --- a/tests/run-make/extern-flag-fun/rmake.rs +++ b/tests/run-make/extern-flag-fun/rmake.rs @@ -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 diff --git a/tests/run-make/extern-multiple-copies/rmake.rs b/tests/run-make/extern-multiple-copies/rmake.rs index d9d769d178c3..01e4beed1b5c 100644 --- a/tests/run-make/extern-multiple-copies/rmake.rs +++ b/tests/run-make/extern-multiple-copies/rmake.rs @@ -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 diff --git a/tests/run-make/extern-multiple-copies2/rmake.rs b/tests/run-make/extern-multiple-copies2/rmake.rs index 4188d5bdc182..5937929a1f3e 100644 --- a/tests/run-make/extern-multiple-copies2/rmake.rs +++ b/tests/run-make/extern-multiple-copies2/rmake.rs @@ -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. diff --git a/tests/run-make/fmt-write-bloat/rmake.rs b/tests/run-make/fmt-write-bloat/rmake.rs index 6875ef9ddc05..3348651d501f 100644 --- a/tests/run-make/fmt-write-bloat/rmake.rs +++ b/tests/run-make/fmt-write-bloat/rmake.rs @@ -15,14 +15,9 @@ //! `NO_DEBUG_ASSERTIONS=1`). If debug assertions are disabled, then we can check for the absence of //! additional `usize` formatting and padding related symbols. -//@ ignore-windows -// Reason: -// - MSVC targets really need to parse the .pdb file (aka the debug information). -// On Windows there's an API for that (dbghelp) which maybe we can use -// - MinGW targets have a lot of symbols included in their runtime which we can't avoid. -// We would need to make the symbols we're looking for more specific for this test to work. //@ ignore-cross-compile +use run_make_support::artifact_names::bin_name; use run_make_support::env::no_debug_assertions; use run_make_support::rustc; use run_make_support::symbols::any_symbol_contains; @@ -36,5 +31,5 @@ fn main() { // otherwise, add them to the list of symbols to deny. panic_syms.extend_from_slice(&["panicking", "panic_fmt", "pad_integral", "Display"]); } - assert!(!any_symbol_contains("main", &panic_syms)); + assert!(!any_symbol_contains(bin_name("main"), &panic_syms)); } diff --git a/tests/run-make/ice-dep-cannot-find-dep/rmake.rs b/tests/run-make/ice-dep-cannot-find-dep/rmake.rs index 1c136773f015..cb3cf39e436f 100644 --- a/tests/run-make/ice-dep-cannot-find-dep/rmake.rs +++ b/tests/run-make/ice-dep-cannot-find-dep/rmake.rs @@ -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. diff --git a/tests/run-make/include-all-symbols-linking/rmake.rs b/tests/run-make/include-all-symbols-linking/rmake.rs index 4f85ee179f5f..61b83e7a07fa 100644 --- a/tests/run-make/include-all-symbols-linking/rmake.rs +++ b/tests/run-make/include-all-symbols-linking/rmake.rs @@ -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. diff --git a/tests/run-make/incr-prev-body-beyond-eof/rmake.rs b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs index cfa8d5b46cd9..cdecf127a2c8 100644 --- a/tests/run-make/incr-prev-body-beyond-eof/rmake.rs +++ b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs @@ -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}; diff --git a/tests/run-make/incr-test-moved-file/rmake.rs b/tests/run-make/incr-test-moved-file/rmake.rs index dfba95d3fedb..9a00a14ae955 100644 --- a/tests/run-make/incr-test-moved-file/rmake.rs +++ b/tests/run-make/incr-test-moved-file/rmake.rs @@ -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}; diff --git a/tests/run-make/intrinsic-unreachable/rmake.rs b/tests/run-make/intrinsic-unreachable/rmake.rs index bb189fbdcb5d..ea9c0a1434a3 100644 --- a/tests/run-make/intrinsic-unreachable/rmake.rs +++ b/tests/run-make/intrinsic-unreachable/rmake.rs @@ -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. diff --git a/tests/run-make/invalid-so/rmake.rs b/tests/run-make/invalid-so/rmake.rs index ee886b5ee3a6..9e5ce583ece2 100644 --- a/tests/run-make/invalid-so/rmake.rs +++ b/tests/run-make/invalid-so/rmake.rs @@ -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 diff --git a/tests/run-make/issue-125484-used-dependencies/rmake.rs b/tests/run-make/issue-125484-used-dependencies/rmake.rs index afcea34783f9..67b0b600b473 100644 --- a/tests/run-make/issue-125484-used-dependencies/rmake.rs +++ b/tests/run-make/issue-125484-used-dependencies/rmake.rs @@ -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. diff --git a/tests/run-make/json-error-no-offset/rmake.rs b/tests/run-make/json-error-no-offset/rmake.rs index 3f45778ca04a..296d968540a6 100644 --- a/tests/run-make/json-error-no-offset/rmake.rs +++ b/tests/run-make/json-error-no-offset/rmake.rs @@ -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. diff --git a/tests/run-make/link-args-order/rmake.rs b/tests/run-make/link-args-order/rmake.rs index a4591ea3949e..7a67c12f74c8 100644 --- a/tests/run-make/link-args-order/rmake.rs +++ b/tests/run-make/link-args-order/rmake.rs @@ -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. diff --git a/tests/run-make/link-dedup/rmake.rs b/tests/run-make/link-dedup/rmake.rs index 0148817f9878..874e6e0083bd 100644 --- a/tests/run-make/link-dedup/rmake.rs +++ b/tests/run-make/link-dedup/rmake.rs @@ -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 diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index eb1bbbff8ef0..26d03fd2d70e 100644 --- a/tests/run-make/linker-warning/rmake.rs +++ b/tests/run-make/linker-warning/rmake.rs @@ -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 { @@ -56,7 +57,8 @@ fn main() { diff() .expected_file("short-error.txt") .actual_text("(linker error)", out.stderr()) - .normalize(r#"/rustc[^/]*/"#, "/rustc/") + .normalize(r#"/rustc[^/_-]*/"#, "/rustc/") + .normalize("libpanic_abort", "libpanic_unwind") .normalize( regex::escape(run_make_support::build_root().to_str().unwrap()), "/build-root", diff --git a/tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs b/tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs index 0d96b40e8a43..70a0853848cc 100644 --- a/tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs +++ b/tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs @@ -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}; diff --git a/tests/run-make/mte-ffi/rmake.rs b/tests/run-make/mte-ffi/rmake.rs index 50f5f14191b4..a8da0dc0ee03 100644 --- a/tests/run-make/mte-ffi/rmake.rs +++ b/tests/run-make/mte-ffi/rmake.rs @@ -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")) diff --git a/tests/run-make/naked-symbol-visibility/rmake.rs b/tests/run-make/naked-symbol-visibility/rmake.rs index c69a9ef9eeb0..d73eafcaefea 100644 --- a/tests/run-make/naked-symbol-visibility/rmake.rs +++ b/tests/run-make/naked-symbol-visibility/rmake.rs @@ -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; diff --git a/tests/run-make/native-lib-alt-naming/rmake.rs b/tests/run-make/native-lib-alt-naming/rmake.rs index a1dc002533f5..e989cece6031 100644 --- a/tests/run-make/native-lib-alt-naming/rmake.rs +++ b/tests/run-make/native-lib-alt-naming/rmake.rs @@ -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() { diff --git a/tests/run-make/native-link-modifier-verbatim-linker/rmake.rs b/tests/run-make/native-link-modifier-verbatim-linker/rmake.rs index e06be13d9b95..4fb0690531a1 100644 --- a/tests/run-make/native-link-modifier-verbatim-linker/rmake.rs +++ b/tests/run-make/native-link-modifier-verbatim-linker/rmake.rs @@ -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; diff --git a/tests/run-make/no-alloc-shim/foo.rs b/tests/run-make/no-alloc-shim/foo.rs index b5d0d394d2b9..a22307f41b39 100644 --- a/tests/run-make/no-alloc-shim/foo.rs +++ b/tests/run-make/no-alloc-shim/foo.rs @@ -12,7 +12,13 @@ fn panic_handler(_: &core::panic::PanicInfo) -> ! { } #[no_mangle] -extern "C" fn rust_eh_personality() { +extern "C" fn rust_eh_personality( + _version: i32, + _actions: i32, + _exception_class: u64, + _exception_object: *mut (), + _context: *mut (), +) -> i32 { loop {} } diff --git a/tests/run-make/no-builtins-attribute/filecheck.main.txt b/tests/run-make/no-builtins-attribute/filecheck.main.txt index ecd650bdca80..7cbe94f57281 100644 --- a/tests/run-make/no-builtins-attribute/filecheck.main.txt +++ b/tests/run-make/no-builtins-attribute/filecheck.main.txt @@ -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 diff --git a/tests/run-make/no-builtins-attribute/rmake.rs b/tests/run-make/no-builtins-attribute/rmake.rs index 038958f19ed9..f08316e14ce7 100644 --- a/tests/run-make/no-builtins-attribute/rmake.rs +++ b/tests/run-make/no-builtins-attribute/rmake.rs @@ -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(); } diff --git a/tests/run-make/no-builtins-lto/rmake.rs b/tests/run-make/no-builtins-lto/rmake.rs index a1d9dc43e713..c7c075f1a66e 100644 --- a/tests/run-make/no-builtins-lto/rmake.rs +++ b/tests/run-make/no-builtins-lto/rmake.rs @@ -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. diff --git a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs index 5c437a3fe00c..aa6b83cf0621 100644 --- a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs +++ b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs @@ -1,4 +1,4 @@ -//@ needs-target-std +//@ ignore-cross-compile use run_make_support::{rfs, rustc}; fn main() { diff --git a/tests/run-make/proc-macro-three-crates/rmake.rs b/tests/run-make/proc-macro-three-crates/rmake.rs index e5a3385acbc5..4dfc32fe7e44 100644 --- a/tests/run-make/proc-macro-three-crates/rmake.rs +++ b/tests/run-make/proc-macro-three-crates/rmake.rs @@ -1,5 +1,7 @@ -//@ needs-target-std -// +//@ ignore-cross-compile +//@ needs-crate-type: proc-macro +//@ ignore-musl (FIXME: can't find `-lunwind`) + // A compiler bug caused the following issue: // If a crate A depends on crate B, and crate B // depends on crate C, and crate C contains a procedural diff --git a/tests/run-make/relro-levels/rmake.rs b/tests/run-make/relro-levels/rmake.rs index 91d106a03e4b..67aa7c155ea6 100644 --- a/tests/run-make/relro-levels/rmake.rs +++ b/tests/run-make/relro-levels/rmake.rs @@ -1,6 +1,7 @@ // This tests the different -Crelro-level values, and makes sure that they work properly. //@ only-linux +//@ ignore-cross-compile use run_make_support::{llvm_readobj, rustc}; diff --git a/tests/run-make/repr128-dwarf/rmake.rs b/tests/run-make/repr128-dwarf/rmake.rs index 1372d2bcc465..96c65d7d8977 100644 --- a/tests/run-make/repr128-dwarf/rmake.rs +++ b/tests/run-make/repr128-dwarf/rmake.rs @@ -1,4 +1,5 @@ -//@ needs-target-std +//@ ignore-cross-compile +//@ ignore-wasm (`object` can't handle wasm object files) //@ ignore-windows // This test should be replaced with one in tests/debuginfo once GDB or LLDB support 128-bit enums. diff --git a/tests/run-make/reproducible-build-2/rmake.rs b/tests/run-make/reproducible-build-2/rmake.rs index 0e1781dbfbe4..1de5ca1e6f7f 100644 --- a/tests/run-make/reproducible-build-2/rmake.rs +++ b/tests/run-make/reproducible-build-2/rmake.rs @@ -6,23 +6,37 @@ // Outputs should be identical. // See https://github.com/rust-lang/rust/issues/34902 -//@ needs-target-std -//@ ignore-windows -// Reasons: -// 1. The object files are reproducible, but their paths are not, which causes -// the first assertion in the test to fail. -// 2. When the sysroot gets copied, some symlinks must be re-created, -// which is a privileged action on Windows. +//@ ignore-cross-compile -use run_make_support::{rfs, rust_lib_name, rustc}; +//@ ignore-windows-gnu +// GNU Linker for Windows is non-deterministic. + +use run_make_support::{bin_name, is_windows_msvc, rfs, rust_lib_name, rustc}; fn main() { // test 1: fat lto rustc().input("reproducible-build-aux.rs").run(); - rustc().input("reproducible-build.rs").arg("-Clto=fat").output("reproducible-build").run(); - rfs::rename("reproducible-build", "reproducible-build-a"); - rustc().input("reproducible-build.rs").arg("-Clto=fat").output("reproducible-build").run(); - assert_eq!(rfs::read("reproducible-build"), rfs::read("reproducible-build-a")); + let make_reproducible_build = || { + let mut reproducible_build = rustc(); + reproducible_build + .input("reproducible-build.rs") + .arg("-Clto=fat") + .output(bin_name("reproducible-build")); + if is_windows_msvc() { + // Avoids timestamps, etc. when linking. + reproducible_build.arg("-Clink-arg=/Brepro"); + } + reproducible_build.run(); + }; + make_reproducible_build(); + rfs::rename(bin_name("reproducible-build"), "reproducible-build-a"); + if is_windows_msvc() { + // Linker acts differently if there is already a PDB file with the same + // name. + rfs::remove_file("reproducible-build.pdb"); + } + make_reproducible_build(); + assert_eq!(rfs::read(bin_name("reproducible-build")), rfs::read("reproducible-build-a")); // test 2: sysroot let sysroot = rustc().print("sysroot").run().stdout_utf8(); diff --git a/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs b/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs index 70d1ead85b5d..50c3f7f6df16 100644 --- a/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs +++ b/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs @@ -1,5 +1,5 @@ -//@ needs-target-std -// +//@ ignore-cross-compile + // `-Z packed_bundled_libs` is an unstable rustc flag that makes the compiler // only require a native library and no supplementary object files to compile. // This test simply checks that this flag can be passed alongside verbatim syntax diff --git a/tests/run-make/rustc-macro-dep-files/rmake.rs b/tests/run-make/rustc-macro-dep-files/rmake.rs index eb4771fea7a6..2eb490e5d23a 100644 --- a/tests/run-make/rustc-macro-dep-files/rmake.rs +++ b/tests/run-make/rustc-macro-dep-files/rmake.rs @@ -1,5 +1,7 @@ -//@ needs-target-std -// +//@ ignore-cross-compile +//@ needs-crate-type: proc-macro +//@ ignore-musl (FIXME: can't find `-lunwind`) + // --emit dep-info used to print all macro-generated code it could // find as if it was part of a nonexistent file named "proc-macro source", // which is not a valid path. After this was fixed in #36776, this test checks @@ -10,7 +12,7 @@ use run_make_support::{diff, rustc, target}; fn main() { rustc().input("foo.rs").run(); - rustc().input("bar.rs").target(target()).emit("dep-info").run(); + rustc().input("bar.rs").emit("dep-info").run(); // The emitted file should not contain "proc-macro source". diff().expected_file("correct.d").actual_file("bar.d").run(); } diff --git a/tests/run-make/rustdoc-default-output/rmake.rs b/tests/run-make/rustdoc-default-output/rmake.rs index 5f9c501e5286..06720445a35c 100644 --- a/tests/run-make/rustdoc-default-output/rmake.rs +++ b/tests/run-make/rustdoc-default-output/rmake.rs @@ -3,10 +3,10 @@ // ensures the output of rustdoc's help menu is as expected. // See https://github.com/rust-lang/rust/issues/88756 -use run_make_support::{diff, rustdoc}; +use run_make_support::{bare_rustdoc, diff}; fn main() { - let out = rustdoc().run().stdout_utf8(); + let out = bare_rustdoc().run().stdout_utf8(); diff() .expected_file("output-default.stdout") .actual_text("actual", out) diff --git a/tests/run-make/rustdoc-dep-info/rmake.rs b/tests/run-make/rustdoc-dep-info/rmake.rs index 6902bfc21ca2..db7a00a5ce21 100644 --- a/tests/run-make/rustdoc-dep-info/rmake.rs +++ b/tests/run-make/rustdoc-dep-info/rmake.rs @@ -1,6 +1,8 @@ // This is a simple smoke test for rustdoc's `--emit dep-info` feature. It prints out // information about dependencies in a Makefile-compatible format, as a `.d` file. +//@ needs-target-std + use run_make_support::assertion_helpers::assert_contains; use run_make_support::{path, rfs, rustdoc}; diff --git a/tests/run-make/rustdoc-determinism/rmake.rs b/tests/run-make/rustdoc-determinism/rmake.rs index 5a030c6f496b..921baef4a979 100644 --- a/tests/run-make/rustdoc-determinism/rmake.rs +++ b/tests/run-make/rustdoc-determinism/rmake.rs @@ -1,6 +1,8 @@ // Assert that the search index is generated deterministically, regardless of the // order that crates are documented in. +//@ needs-target-std + use run_make_support::{diff, path, rustdoc}; fn main() { diff --git a/tests/run-make/rustdoc-error-lines/rmake.rs b/tests/run-make/rustdoc-error-lines/rmake.rs index 0d8c500ed1e0..e15d91e9387a 100644 --- a/tests/run-make/rustdoc-error-lines/rmake.rs +++ b/tests/run-make/rustdoc-error-lines/rmake.rs @@ -1,6 +1,8 @@ // Assert that the search index is generated deterministically, regardless of the // order that crates are documented in. +//@ needs-target-std + use run_make_support::rustdoc; fn main() { diff --git a/tests/run-make/rustdoc-io-error/rmake.rs b/tests/run-make/rustdoc-io-error/rmake.rs index 31441d7ebc5c..766091abf97c 100644 --- a/tests/run-make/rustdoc-io-error/rmake.rs +++ b/tests/run-make/rustdoc-io-error/rmake.rs @@ -13,6 +13,7 @@ // containers would use a non-root user, but this leads to issues with // `mkfs.ext4 -d`, as well as mounting a loop device for the rootfs. //@ ignore-windows - the `set_readonly` functions doesn't work on folders. +//@ needs-target-std use run_make_support::{path, rfs, rustdoc}; diff --git a/tests/run-make/rustdoc-map-file/rmake.rs b/tests/run-make/rustdoc-map-file/rmake.rs index 50dcc603c02f..802c924d580d 100644 --- a/tests/run-make/rustdoc-map-file/rmake.rs +++ b/tests/run-make/rustdoc-map-file/rmake.rs @@ -1,6 +1,8 @@ // This test ensures that all items from `foo` are correctly generated into the `redirect-map.json` // file with `--generate-redirect-map` rustdoc option. +//@ needs-target-std + use run_make_support::rfs::read_to_string; use run_make_support::{path, rustdoc, serde_json}; diff --git a/tests/run-make/rustdoc-output-path/rmake.rs b/tests/run-make/rustdoc-output-path/rmake.rs index 7f6accf26c21..cece914e947b 100644 --- a/tests/run-make/rustdoc-output-path/rmake.rs +++ b/tests/run-make/rustdoc-output-path/rmake.rs @@ -1,5 +1,7 @@ // Checks that if the output folder doesn't exist, rustdoc will create it. +//@ needs-target-std + use run_make_support::{path, rustdoc}; fn main() { diff --git a/tests/run-make/rustdoc-output-stdout/rmake.rs b/tests/run-make/rustdoc-output-stdout/rmake.rs index d2fd04511635..e6c007978bdc 100644 --- a/tests/run-make/rustdoc-output-stdout/rmake.rs +++ b/tests/run-make/rustdoc-output-stdout/rmake.rs @@ -1,6 +1,8 @@ // This test verifies that rustdoc `-o -` prints JSON on stdout and doesn't generate // a JSON file. +//@ needs-target-std + use run_make_support::path_helpers::{cwd, has_extension, read_dir_entries_recursive}; use run_make_support::{rustdoc, serde_json}; diff --git a/tests/run-make/rustdoc-test-args/rmake.rs b/tests/run-make/rustdoc-test-args/rmake.rs index fddb3795402e..7c0223cf7329 100644 --- a/tests/run-make/rustdoc-test-args/rmake.rs +++ b/tests/run-make/rustdoc-test-args/rmake.rs @@ -1,3 +1,5 @@ +//@ ignore-cross-compile (needs to run doctest binary) + use std::iter; use std::path::Path; diff --git a/tests/run-make/rustdoc-themes/rmake.rs b/tests/run-make/rustdoc-themes/rmake.rs index 4577e47d47e7..681e6baaee36 100644 --- a/tests/run-make/rustdoc-themes/rmake.rs +++ b/tests/run-make/rustdoc-themes/rmake.rs @@ -1,5 +1,7 @@ // Test that rustdoc will properly load in a theme file and display it in the theme selector. +//@ needs-target-std + use std::path::Path; use run_make_support::{htmldocck, rfs, rustdoc, source_root}; diff --git a/tests/run-make/rustdoc-verify-output-files/rmake.rs b/tests/run-make/rustdoc-verify-output-files/rmake.rs index a4d4050b7450..181d321997b0 100644 --- a/tests/run-make/rustdoc-verify-output-files/rmake.rs +++ b/tests/run-make/rustdoc-verify-output-files/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std + use std::path::{Path, PathBuf}; use run_make_support::{assert_dirs_are_equal, rfs, rustdoc}; diff --git a/tests/run-make/rustdoc-with-out-dir-option/rmake.rs b/tests/run-make/rustdoc-with-out-dir-option/rmake.rs index a82a1965a9c9..231a5b36600e 100644 --- a/tests/run-make/rustdoc-with-out-dir-option/rmake.rs +++ b/tests/run-make/rustdoc-with-out-dir-option/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std + use run_make_support::{htmldocck, rustdoc}; fn main() { diff --git a/tests/run-make/rustdoc-with-output-option/rmake.rs b/tests/run-make/rustdoc-with-output-option/rmake.rs index f7fbbec6986c..2c1b76f5b9cf 100644 --- a/tests/run-make/rustdoc-with-output-option/rmake.rs +++ b/tests/run-make/rustdoc-with-output-option/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std + use run_make_support::{htmldocck, rustdoc}; fn main() { diff --git a/tests/run-make/sanitizer-dylib-link/program.rs b/tests/run-make/sanitizer-dylib-link/program.rs index 1026c7f89ba9..dbf885d343fe 100644 --- a/tests/run-make/sanitizer-dylib-link/program.rs +++ b/tests/run-make/sanitizer-dylib-link/program.rs @@ -1,4 +1,4 @@ -#[cfg_attr(windows, link(name = "library.dll.lib", modifiers = "+verbatim"))] +#[cfg_attr(windows, link(name = "library", kind = "raw-dylib"))] #[cfg_attr(not(windows), link(name = "library"))] extern "C" { fn overflow(); diff --git a/tests/run-make/share-generics-dylib/rmake.rs b/tests/run-make/share-generics-dylib/rmake.rs index 2d52cd43db75..ae9e51abffd7 100644 --- a/tests/run-make/share-generics-dylib/rmake.rs +++ b/tests/run-make/share-generics-dylib/rmake.rs @@ -1,5 +1,7 @@ -//@ needs-target-std -// +//@ ignore-cross-compile +//@ needs-dynamic-linking +//@ needs-crate-type: dylib + // This test makes sure all generic instances get re-exported from Rust dylibs for use by // `-Zshare-generics`. There are two rlibs (`instance_provider_a` and `instance_provider_b`) // which both provide an instance of `Cell::set`. There is `instance_user_dylib` which is diff --git a/tests/run-make/short-ice/rmake.rs b/tests/run-make/short-ice/rmake.rs index 8377954f4672..483def62fc79 100644 --- a/tests/run-make/short-ice/rmake.rs +++ b/tests/run-make/short-ice/rmake.rs @@ -5,8 +5,9 @@ // See https://github.com/rust-lang/rust/issues/107910 //@ needs-target-std -//@ ignore-windows -// Reason: the assert_eq! on line 32 fails, as error output on Windows is different. +//@ ignore-i686-pc-windows-msvc +// Reason: the assert_eq! on line 37 fails, almost seems like it missing debug info? +// Haven't been able to reproduce locally, but it happens on CI. use run_make_support::rustc; @@ -29,10 +30,16 @@ fn main() { let rustc_query_count_full = count_lines_with(rust_test_log_2, "rustc_query_"); - assert!(rust_test_log_1.lines().count() < rust_test_log_2.lines().count()); + assert!( + rust_test_log_1.lines().count() < rust_test_log_2.lines().count(), + "Short backtrace should be shorter than full backtrace.\nShort backtrace:\n\ + {rust_test_log_1}\nFull backtrace:\n{rust_test_log_2}" + ); assert_eq!( count_lines_with(rust_test_log_2, "__rust_begin_short_backtrace"), - count_lines_with(rust_test_log_2, "__rust_end_short_backtrace") + count_lines_with(rust_test_log_2, "__rust_end_short_backtrace"), + "Full backtrace should contain the short backtrace markers.\nFull backtrace:\n\ + {rust_test_log_2}" ); assert!(count_lines_with(rust_test_log_1, "rustc_query_") + 5 < rustc_query_count_full); assert!(rustc_query_count_full > 5); diff --git a/tests/run-make/static-pie/rmake.rs b/tests/run-make/static-pie/rmake.rs index 1557c170f56d..cb24c0495be8 100644 --- a/tests/run-make/static-pie/rmake.rs +++ b/tests/run-make/static-pie/rmake.rs @@ -49,7 +49,6 @@ fn test(compiler: &str) { rustc() .input("test-aslr.rs") - .target(target()) .linker(compiler) .arg("-Clinker-flavor=gcc") .arg("-Ctarget-feature=+crt-static") diff --git a/tests/run-make/staticlib-thin-archive/rmake.rs b/tests/run-make/staticlib-thin-archive/rmake.rs index 1fb56ac05381..5281e9f8c9cc 100644 --- a/tests/run-make/staticlib-thin-archive/rmake.rs +++ b/tests/run-make/staticlib-thin-archive/rmake.rs @@ -1,5 +1,5 @@ -//@ needs-target-std -// +//@ ignore-cross-compile + // Regression test for https://github.com/rust-lang/rust/issues/107407 which // checks that rustc can read thin archive. Before the object crate added thin // archive support rustc would add emit object files to the staticlib and after diff --git a/tests/run-make/stdin-rustc/rmake.rs b/tests/run-make/stdin-rustc/rmake.rs index 318d569a7605..6ae33766b90f 100644 --- a/tests/run-make/stdin-rustc/rmake.rs +++ b/tests/run-make/stdin-rustc/rmake.rs @@ -1,9 +1,9 @@ -//@ needs-target-std +//@ ignore-cross-compile //! This test checks rustc `-` (stdin) support use std::path::PathBuf; -use run_make_support::{is_windows, rustc}; +use run_make_support::{bin_name, rustc}; const HELLO_WORLD: &str = r#" fn main() { @@ -16,11 +16,7 @@ const NOT_UTF8: &[u8] = &[0xff, 0xff, 0xff]; fn main() { // echo $HELLO_WORLD | rustc - rustc().arg("-").stdin_buf(HELLO_WORLD).run(); - assert!( - PathBuf::from(if !is_windows() { "rust_out" } else { "rust_out.exe" }) - .try_exists() - .unwrap() - ); + assert!(PathBuf::from(bin_name("rust_out")).try_exists().unwrap()); // echo $NOT_UTF8 | rustc - rustc().arg("-").stdin_buf(NOT_UTF8).run_fail().assert_stderr_contains( diff --git a/tests/run-make/stdin-rustdoc/rmake.rs b/tests/run-make/stdin-rustdoc/rmake.rs index 30f97b8a2cd7..0420eac19932 100644 --- a/tests/run-make/stdin-rustdoc/rmake.rs +++ b/tests/run-make/stdin-rustdoc/rmake.rs @@ -1,3 +1,5 @@ +//@ ignore-cross-compile (needs to run doctests) + //! This test checks rustdoc `-` (stdin) handling use std::path::PathBuf; diff --git a/tests/run-make/symbol-visibility/rmake.rs b/tests/run-make/symbol-visibility/rmake.rs index 0175158d08b8..49c8e87707b6 100644 --- a/tests/run-make/symbol-visibility/rmake.rs +++ b/tests/run-make/symbol-visibility/rmake.rs @@ -1,5 +1,7 @@ -//@ needs-target-std -// +//@ ignore-cross-compile +//@ needs-crate-type: dylib, cdylib, proc-macro +//@ needs-dynamic-linking + // Dynamic libraries on Rust used to export a very high amount of symbols, // going as far as filling the output with mangled names and generic function // names. After the rework of #38117, this test checks that no mangled Rust symbols diff --git a/tests/run-make/sysroot-crates-are-unstable/rmake.rs b/tests/run-make/sysroot-crates-are-unstable/rmake.rs index c81c7fafdab0..20ad01bef61d 100644 --- a/tests/run-make/sysroot-crates-are-unstable/rmake.rs +++ b/tests/run-make/sysroot-crates-are-unstable/rmake.rs @@ -31,7 +31,6 @@ fn check_crate_is_unstable(cr: &Crate) { // Trying to use this crate from a user program should fail. let output = rustc() .crate_type("rlib") - .target(target()) .extern_(name, path) .input("-") .stdin_buf(format!("extern crate {name};")) diff --git a/tests/run-make/textrel-on-minimal-lib/rmake.rs b/tests/run-make/textrel-on-minimal-lib/rmake.rs index 625ded70ad62..08e2b45a75f4 100644 --- a/tests/run-make/textrel-on-minimal-lib/rmake.rs +++ b/tests/run-make/textrel-on-minimal-lib/rmake.rs @@ -6,25 +6,23 @@ // See https://github.com/rust-lang/rust/issues/68794 //@ ignore-cross-compile -//@ ignore-windows -// Reason: There is no `bar.dll` produced by CC to run readobj on use run_make_support::{ - cc, dynamic_lib_name, extra_c_flags, extra_cxx_flags, llvm_readobj, rustc, static_lib_name, + bin_name, cc, extra_c_flags, extra_cxx_flags, llvm_readobj, rustc, static_lib_name, }; fn main() { rustc().input("foo.rs").run(); cc().input("bar.c") .input(static_lib_name("foo")) - .out_exe(&dynamic_lib_name("bar")) + .out_exe(&bin_name("bar")) .arg("-fPIC") .arg("-shared") .args(extra_c_flags()) .args(extra_cxx_flags()) .run(); llvm_readobj() - .input(dynamic_lib_name("bar")) + .input(bin_name("bar")) .arg("--dynamic") .run() .assert_stdout_not_contains("TEXTREL"); diff --git a/tests/run-make/track-path-dep-info/rmake.rs b/tests/run-make/track-path-dep-info/rmake.rs index 4b98a1b48d5f..955c46f7e682 100644 --- a/tests/run-make/track-path-dep-info/rmake.rs +++ b/tests/run-make/track-path-dep-info/rmake.rs @@ -1,5 +1,7 @@ -//@ needs-target-std -// +//@ ignore-cross-compile +//@ needs-crate-type: proc-macro +//@ ignore-musl (FIXME: can't find `-lunwind`) + // This test checks the functionality of `tracked_path::path`, a procedural macro // feature that adds a dependency to another file inside the procmacro. In this case, // the text file is added through this method, and the test checks that the compilation diff --git a/tests/run-make/used/rmake.rs b/tests/run-make/used/rmake.rs index daed69c1b385..bcdb84132d3f 100644 --- a/tests/run-make/used/rmake.rs +++ b/tests/run-make/used/rmake.rs @@ -1,5 +1,6 @@ //@ needs-target-std -// +//@ ignore-wasm (`object` can't handle wasm object files) + // This test ensures that the compiler is keeping static variables, even if not referenced // by another part of the program, in the output object file. // diff --git a/tests/rustdoc-js-std/doc-alias-use.js b/tests/rustdoc-js-std/doc-alias-use.js new file mode 100644 index 000000000000..e08d94533a93 --- /dev/null +++ b/tests/rustdoc-js-std/doc-alias-use.js @@ -0,0 +1,12 @@ +// AsciiChar has a doc alias on its reexport and we +// want to make sure that actually works correctly, +// since apperently there are no other tests for this. + +const EXPECTED = [ + { + 'query': 'AsciiChar', + 'others': [ + { 'path': 'core::ascii', 'name': 'Char' }, + ], + }, +]; diff --git a/tests/rustdoc-js/big-result.rs b/tests/rustdoc-js/big-result.rs index 4dfecd6aaadd..c7a52aac1a24 100644 --- a/tests/rustdoc-js/big-result.rs +++ b/tests/rustdoc-js/big-result.rs @@ -1,4 +1,3 @@ -#![feature(concat_idents)] #![allow(nonstandard_style)] /// Generate 250 items that all match the query, starting with the longest. /// Those long items should be dropped from the result set, and the short ones diff --git a/tests/rustdoc-json/attrs/cold.rs b/tests/rustdoc-json/attrs/cold.rs new file mode 100644 index 000000000000..e219345d669c --- /dev/null +++ b/tests/rustdoc-json/attrs/cold.rs @@ -0,0 +1,3 @@ +//@ is "$.index[?(@.name=='cold_fn')].attrs" '["#[attr = Cold]"]' +#[cold] +pub fn cold_fn() {} diff --git a/tests/rustdoc-json/attrs/must_use.rs b/tests/rustdoc-json/attrs/must_use.rs index 64df8e5f509f..3ca6f5a75a5a 100644 --- a/tests/rustdoc-json/attrs/must_use.rs +++ b/tests/rustdoc-json/attrs/must_use.rs @@ -1,9 +1,9 @@ #![no_std] -//@ is "$.index[?(@.name=='example')].attrs" '["#[must_use]"]' +//@ is "$.index[?(@.name=='example')].attrs" '["#[attr = MustUse]"]' #[must_use] pub fn example() -> impl Iterator {} -//@ is "$.index[?(@.name=='explicit_message')].attrs" '["#[must_use = \"does nothing if you do not use it\"]"]' +//@ is "$.index[?(@.name=='explicit_message')].attrs" '["#[attr = MustUse {reason: \"does nothing if you do not use it\"}]"]' #[must_use = "does nothing if you do not use it"] pub fn explicit_message() -> impl Iterator {} diff --git a/tests/rustdoc-json/attrs/optimize.rs b/tests/rustdoc-json/attrs/optimize.rs new file mode 100644 index 000000000000..0bed0ad18c31 --- /dev/null +++ b/tests/rustdoc-json/attrs/optimize.rs @@ -0,0 +1,13 @@ +#![feature(optimize_attribute)] + +//@ is "$.index[?(@.name=='speed')].attrs" '["#[attr = Optimize(Speed)]"]' +#[optimize(speed)] +pub fn speed() {} + +//@ is "$.index[?(@.name=='size')].attrs" '["#[attr = Optimize(Size)]"]' +#[optimize(size)] +pub fn size() {} + +//@ is "$.index[?(@.name=='none')].attrs" '["#[attr = Optimize(DoNotOptimize)]"]' +#[optimize(none)] +pub fn none() {} diff --git a/tests/rustdoc-json/generic-args.rs b/tests/rustdoc-json/generic-args.rs new file mode 100644 index 000000000000..b4a73a046b50 --- /dev/null +++ b/tests/rustdoc-json/generic-args.rs @@ -0,0 +1,23 @@ +pub struct MyStruct(u32); + +pub trait MyTrait { + type MyType; + fn my_fn(&self); +} + +impl MyTrait for MyStruct { + type MyType = u32; + fn my_fn(&self) {} +} + +//@ is "$.index[?(@.name=='my_fn1')].inner.function.sig.inputs[0][1].qualified_path.args" null +//@ is "$.index[?(@.name=='my_fn1')].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.args" null +pub fn my_fn1(_: ::MyType) {} + +//@ is "$.index[?(@.name=='my_fn2')].inner.function.sig.inputs[0][1].dyn_trait.traits[0].trait.args.angle_bracketed.constraints[0].args" null +pub fn my_fn2(_: IntoIterator) {} + +//@ is "$.index[?(@.name=='my_fn3')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.args.parenthesized.inputs" [] +pub fn my_fn3(f: impl FnMut()) {} + +fn main() {} diff --git a/tests/rustdoc/target-feature.rs b/tests/rustdoc/target-feature.rs new file mode 100644 index 000000000000..59a08a0ca949 --- /dev/null +++ b/tests/rustdoc/target-feature.rs @@ -0,0 +1,38 @@ +#![crate_name = "foo"] + +//@ has 'foo/index.html' + +//@ has - '//dl[@class="item-table"]/dt[1]//a' 'f1_safe' +//@ has - '//dl[@class="item-table"]/dt[1]//code' 'popcnt' +//@ count - '//dl[@class="item-table"]/dt[1]//sup' 0 +//@ has - '//dl[@class="item-table"]/dt[2]//a' 'f2_not_safe' +//@ has - '//dl[@class="item-table"]/dt[2]//code' 'avx2' +//@ count - '//dl[@class="item-table"]/dt[2]//sup' 1 +//@ has - '//dl[@class="item-table"]/dt[2]//sup' '⚠' + +#[target_feature(enable = "popcnt")] +//@ has 'foo/fn.f1_safe.html' +//@ matches - '//pre[@class="rust item-decl"]' '^pub fn f1_safe' +//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ +// 'Available with target feature popcnt only.' +pub fn f1_safe() {} + +//@ has 'foo/fn.f2_not_safe.html' +//@ matches - '//pre[@class="rust item-decl"]' '^pub unsafe fn f2_not_safe()' +//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ +// 'Available with target feature avx2 only.' +#[target_feature(enable = "avx2")] +pub unsafe fn f2_not_safe() {} + +//@ has 'foo/fn.f3_multifeatures_in_attr.html' +//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ +// 'Available on target features popcnt and avx2 only.' +#[target_feature(enable = "popcnt", enable = "avx2")] +pub fn f3_multifeatures_in_attr() {} + +//@ has 'foo/fn.f4_multi_attrs.html' +//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ +// 'Available on target features popcnt and avx2 only.' +#[target_feature(enable = "popcnt")] +#[target_feature(enable = "avx2")] +pub fn f4_multi_attrs() {} diff --git a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs index 90e07bed40e7..72b5cfb90630 100644 --- a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs +++ b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs @@ -92,6 +92,21 @@ static EXPRS: &[&str] = &[ "#[attr] loop {}.field", "(#[attr] loop {}).field", "loop { #![attr] }.field", + // Attributes on a Binary, Cast, Assign, AssignOp, and Range expression + // require parentheses. Without parentheses `#[attr] lo..hi` means + // `(#[attr] lo)..hi`, and `#[attr] ..hi` is invalid syntax. + "#[attr] (1 + 1)", + "#[attr] (1 as T)", + "#[attr] (x = 1)", + "#[attr] (x += 1)", + "#[attr] (lo..hi)", + "#[attr] (..hi)", + // If the attribute were not present on the binary operation, it would be + // legal to render this without not just the inner parentheses, but also the + // outer ones. `return x + .. .field` (Yes, really.) Currently the + // pretty-printer does not take advantage of this edge case. + "(return #[attr] (x + ..)).field", + "(return x + ..).field", // Grammar restriction: break value starting with a labeled loop is not // allowed, except if the break is also labeled. "break 'outer 'inner: loop {} + 2", @@ -158,7 +173,12 @@ struct Unparenthesize; impl MutVisitor for Unparenthesize { fn visit_expr(&mut self, e: &mut Expr) { while let ExprKind::Paren(paren) = &mut e.kind { + let paren_attrs = mem::take(&mut e.attrs); *e = mem::replace(paren, Expr::dummy()); + if !paren_attrs.is_empty() { + assert!(e.attrs.is_empty()); + e.attrs = paren_attrs; + } } mut_visit::walk_expr(self, e); } diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs index fa651baa7bc8..87504b8301f0 100644 --- a/tests/ui-fulldeps/run-compiler-twice.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -18,7 +18,7 @@ extern crate rustc_span; use std::path::{Path, PathBuf}; use rustc_interface::{Linker, interface}; -use rustc_session::config::{Input, Options, OutFileName, OutputType, OutputTypes}; +use rustc_session::config::{Input, Options, OutFileName, OutputType, OutputTypes, Sysroot}; use rustc_span::FileName; fn main() { @@ -32,7 +32,7 @@ fn main() { panic!("expected sysroot (and optional linker)"); } - let sysroot = PathBuf::from(&args[1]); + let sysroot = Sysroot::new(Some(PathBuf::from(&args[1]))); let linker = args.get(2).map(PathBuf::from); // compiletest sets the current dir to `output_base_dir` when running. @@ -43,7 +43,7 @@ fn main() { compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref()); } -fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path>) { +fn compile(code: String, output: PathBuf, sysroot: Sysroot, linker: Option<&Path>) { let mut opts = Options::default(); opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]); opts.sysroot = sysroot; diff --git a/tests/ui-fulldeps/rustc-dev-remap.only-remap.stderr b/tests/ui-fulldeps/rustc-dev-remap.only-remap.stderr index f54b6803b346..0c969b9c6d82 100644 --- a/tests/ui-fulldeps/rustc-dev-remap.only-remap.stderr +++ b/tests/ui-fulldeps/rustc-dev-remap.only-remap.stderr @@ -9,6 +9,7 @@ LL | type Result = NotAValidResultType; ControlFlow note: required by a bound in `rustc_ast::visit::Visitor::Result` --> /rustc-dev/xyz/compiler/rustc_ast/src/visit.rs:LL:COL + = note: this error originates in the macro `common_visitor_and_walkers` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr b/tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr index 438c23458e2f..6ac8c3046f62 100644 --- a/tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr +++ b/tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr @@ -10,8 +10,9 @@ LL | type Result = NotAValidResultType; note: required by a bound in `rustc_ast::visit::Visitor::Result` --> $COMPILER_DIR_REAL/rustc_ast/src/visit.rs:LL:COL | -LL | type Result: VisitorResult = (); - | ^^^^^^^^^^^^^ required by this bound in `Visitor::Result` +LL | common_visitor_and_walkers!(Visitor<'a>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Visitor::Result` + = note: this error originates in the macro `common_visitor_and_walkers` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/SUMMARY.md b/tests/ui/SUMMARY.md new file mode 100644 index 000000000000..72b673dd50a2 --- /dev/null +++ b/tests/ui/SUMMARY.md @@ -0,0 +1,1596 @@ +# UI Test Suite Categories + +This is a high-level summary of the organization of the UI test suite (`tests/ui/`). It is not intended to be *prescriptive*, but instead provide a quick survey of existing groupings. + +For now, only immediate subdirectories under `tests/ui/` are described, but these subdirectories can themselves include a `SUMMARY.md` to further describe their own organization and intent, should that be helpful. + +## `tests/ui/abi` + +These tests deal with *Application Binary Interfaces* (ABI), mostly relating to function name mangling (and the `#[no_mangle]` attribute), calling conventions, or compiler flags which affect ABI. + +Tests for unsupported ABIs can be made cross-platform by using the `extern "rust-invalid"` ABI, which is considered unsupported on every platform. + +## `tests/ui/allocator` + +These tests exercise `#![feature(allocator_api)]` and the `#[global_allocator]` attribute. + +See [Allocator traits and `std::heap` #32838](https://github.com/rust-lang/rust/issues/32838). + +## `tests/ui/alloc-error` + +These tests exercise alloc error handling. + +See . + +## `tests/ui/annotate-snippet` + +These tests exercise the [`annotate-snippets`]-based emitter implementation. + +[`annotate-snippets`] is an initiative to share the diagnostics emitting infrastructure between rustc and cargo to reduce duplicate maintenance effort and divergence. See about the initiative. + +[`annotate-snippets`]: https://github.com/rust-lang/annotate-snippets-rs + +## `tests/ui/anon-params` + +These tests deal with anonymous parameters (no name, only type), a deprecated feature that becomes a hard error in Edition 2018. + +## `tests/ui/argfile`: External files providing command line arguments + +These tests exercise rustc reading command line arguments from an externally provided argfile (`@argsfile`). + +See [Implement `@argsfile` to read arguments from command line #63576](https://github.com/rust-lang/rust/issues/63576). + +## `tests/ui/array-slice-vec`: Arrays, slices and vectors + +Exercises various aspects surrounding basic collection types `[]`, `&[]` and `Vec`. E.g. type-checking, out-of-bounds indices, attempted instructions which are allowed in other programming languages, and more. + +## `tests/ui/argument-suggestions`: Argument suggestions + +Calling a function with the wrong number of arguments causes a compilation failure, but the compiler is able to, in some cases, provide suggestions on how to fix the error, such as which arguments to add or delete. These tests exercise the quality of such diagnostics. + +## `tests/ui/asm`: `asm!` macro + +These tests exercise the `asm!` macro, which is used for adding inline assembly. + +See: + +- [Inline assembly | Reference](https://doc.rust-lang.org/reference/inline-assembly.html) +- [`core::arch::asm`](https://doc.rust-lang.org/core/arch/macro.asm.html) +- [`core::arch::global_asm`](https://doc.rust-lang.org/core/arch/macro.global_asm.html) + +This directory contains subdirectories representing various architectures such as `riscv` or `aarch64`. If a test is specifically related to an architecture's particularities, it should be placed within the appropriate subdirectory.Architecture-agnostic tests should be placed below `tests/ui/asm/` directly. + +## `tests/ui/associated-consts`: Associated Constants + +These tests exercise associated constants in traits and impls, on aspects such as definitions, usage, and type checking in associated contexts. + +## `tests/ui/associated-inherent-types`: Inherent Associated Types + +These tests cover associated types defined directly within inherent impls (not in traits). + +See [RFC 0195 Associated items - Inherent associated items](https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md#inherent-associated-items). + +## `tests/ui/associated-item`: Associated Items + +Tests for all kinds of associated items within traits and implementations. This directory serves as a catch-all for tests that don't fit the other more specific associated item directories. + +## `tests/ui/associated-type-bounds`: Associated Type Bounds + +These tests exercise associated type bounds, the feature that gives users a shorthand to express nested type bounds that would otherwise need to be expressed with nested `impl Trait` or broken into several `where` clauses. + +See: + +- [RFC 2289 Associated Type Bounds](https://rust-lang.github.io/rfcs/2289-associated-type-bounds.html) +- [Stabilize associated type bounds (RFC 2289) #122055](https://github.com/rust-lang/rust/pull/122055) + +## `tests/ui/associated-types`: Trait Associated Types + +Tests focused on associated types. If the associated type is not in a trait definition, it belongs in the `tests/ui/associated-inherent-types/` directory. Aspects exercised include e.g. default associated types, overriding defaults, and type inference. + +See [Associated Types | Reference](https://doc.rust-lang.org/reference/items/associated-items.html#associated-types). + +## `tests/ui/async-await`: Async/Await + +Tests for the async/await related features. E.g. async functions, await expressions, and their interaction with other language features. + +## `tests/ui/attributes`: Compiler Attributes + +Tests for language attributes and compiler attributes. E.g. built-in attributes like `#[derive(..)]`, `#[cfg(..)]`, and `#[repr(..)]`, or proc-macro attributes. See [Attributes | Reference](https://doc.rust-lang.org/reference/attributes.html). + +## `tests/ui/auto-traits`: Auto Traits + +There are built-in auto traits (`Send`, `Sync`, etc.) but it is possible to define more with the unstable keyword `auto` through `#![feature(auto_traits)]`. + +See [Tracking Issue for auto traits (`auto_traits`) -- formerly called opt-in built-in traits (`optin_builtin_traits`) #13231](https://github.com/rust-lang/rust/issues/13231). + +## `tests/ui/autodiff`: Automatic Differentiation + +The `#[autodiff]` macro supports automatic differentiation. + +See [Tracking Issue for autodiff #124509](https://github.com/rust-lang/rust/issues/124509). + +## `tests/ui/autoref-autoderef`: Automatic Referencing/Dereferencing + +Tests for automatic referencing and dereferencing behavior, such as automatically adding reference operations (`&` or `&mut`) to make a value match a method's receiver type. Sometimes abbreviated as "auto-ref" or "auto-deref". + +## `tests/ui/auxiliary/`: Auxiliary files for tests directly under `tests/ui`. + +This top-level `auxiliary` subdirectory contains support files for tests immediately under `tests/ui/`. + +**FIXME(#133895)**: tests immediately under `tests/ui/` should be rehomed to more suitable subdirectories, after which this subdirectory can be removed. + +## `tests/ui/backtrace/`: Backtraces + +Runtime panics and error handling generate backtraces to assist in debugging and diagnostics. + +## `tests/ui/bench/`: Benchmarks and performance + +This directory was originally meant to contain tests related to time complexity and benchmarking. + +However, only a single test was ever added to this category: https://github.com/rust-lang/rust/pull/32062 + +**FIXME**: It is also unclear what would happen were this test to "fail" - would it cause the test suite to remain stuck on this test for a much greater duration than normal? + +## `tests/ui/binding/`: Pattern Binding + +Tests for pattern binding in match expressions, let statements, and other binding contexts. E.g. binding modes and refutability. See [Patterns | Reference](https://doc.rust-lang.org/reference/patterns.html). + +## `tests/ui/binop/`: Binary operators + +Tests for binary operators (such as `==`, `&&` or `^`). E.g. overloading, type checking, and diagnostics for invalid operations. + +## `tests/ui/blind/`: `struct` or `mod` inside a `mod` having a duplicate identifier + +Tests exercising name resolution. + +**FIXME**: Probably move to `tests/ui/resolve/`. + +## `tests/ui/block-result/`: Block results and returning + +Tests for block expression results. E.g. specifying the correct return types, semicolon handling, type inference, and expression/statement differences (for example, the difference between `1` and `1;`). + +## `tests/ui/bootstrap/`: RUSTC_BOOTSTRAP environment variable + +Meta tests for stability mechanisms surrounding [`RUSTC_BOOTSTRAP`](https://doc.rust-lang.org/nightly/unstable-book/compiler-environment-variables/RUSTC_BOOTSTRAP.html), which is coordinated between `rustc` and the build system, `bootstrap`. + +## `tests/ui/borrowck/`: Borrow Checking + +Tests for borrow checking. E.g. lifetime analysis, borrowing rules, and diagnostics. + +## `tests/ui/box/`: Box Behavior + +Tests for `Box` smart pointer and `#![feature(box_patterns)]`. E.g. allocation, deref coercion, and edge cases in box pattern matching and placement. + +See: + +- [`std::box::Boxed`](https://doc.rust-lang.org/std/boxed/struct.Box.html) +- [Tracking issue for `box_patterns` feature #29641](https://github.com/rust-lang/rust/issues/29641) + +## `tests/ui/btreemap/`: B-Tree Maps + +Tests focused on `BTreeMap` collections and their compiler interactions. E.g. collection patterns, iterator behavior, and trait implementations specific to `BTreeMap`. See [`std::collections::BTreeMap`](https://doc.rust-lang.org/std/collections/struct.BTreeMap.html). + +## `tests/ui/builtin-superkinds/`: Built-in Trait Hierarchy Tests + +Tests for built-in trait hierarchy (Send, Sync, Sized, etc.) and their supertrait relationships. E.g. auto traits and marker trait constraints. + +See [RFC 3729: Hierarchy of Sized traits](https://github.com/rust-lang/rfcs/pull/3729). + +Defining custom auto traits with the `auto` keyword belongs to `tests/ui/auto-traits/` instead. + +## `tests/ui/cast/`: Type Casting + +Tests for type casting using the `as` operator. Includes tests for valid/invalid casts between primitive types, trait objects, and custom types. For example, check that trying to cast `i32` into `bool` results in a helpful error message. + +See [Type cast expressions | Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html). + +## `tests/ui/cfg/`: Configuration Attribute + +Tests for `#[cfg]` conditional compilation attribute. E.g. feature flags, target architectures, and other configuration predicates and options. + +See [Conditional compilation | Reference](https://doc.rust-lang.org/reference/conditional-compilation.html). + +## `tests/ui/check-cfg/`: Configuration Checks + +Tests for the `--check-cfg` compiler mechanism for checking cfg configurations, for `#[cfg(..)]` and `cfg!(..)`. + +See [Checking conditional configurations | The rustc book](https://doc.rust-lang.org/rustc/check-cfg.html). + +## `tests/ui/closure_context/`: Closure type inference in context + +Tests for closure type inference with respect to surrounding scopes, mostly quality of diagnostics. + +## `tests/ui/closure-expected-type/`: Closure type inference + +Tests targeted at how we deduce the types of closure arguments. This process is a result of some heuristics which take into account the *expected type* we have alongside the *actual types* that we get from inputs. + +**FIXME**: Appears to have significant overlap with `tests/ui/closure_context` and `tests/ui/functions-closures/closure-expected-type`. Needs further investigation. + +## `tests/ui/closures/`: General Closure Tests + +Any closure-focused tests that does not fit in the other more specific closure subdirectories belong here. E.g. syntax, `move`, lifetimes. + +## `tests/ui/cmse-nonsecure/`: `cmse-nonsecure` ABIs + +Tests for `extern "cmse-nonsecure-call"` and `extern "cmse-nonsecure-entry"` functions. Used specifically for the Armv8-M architecture, the former marks Secure functions with additional behaviours, such as adding a special symbol and constraining the number of parameters, while the latter alters function pointers to indicate they are non-secure and to handle them differently than usual. + +See: + +- [`cmse_nonsecure_entry` | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/language-features/cmse-nonsecure-entry.html) +- [`abi_cmse_nonsecure_call` | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/language-features/abi-cmse-nonsecure-call.html) + +## `tests/ui/codegen/`: Code Generation + +Tests that exercise code generation. E.g. codegen flags (starting with `-C` on the command line), LLVM IR output, optimizations (and the various `opt-level`s), and target-specific code generation (such as tests specific to `x86_64`). + +## `tests/ui/codemap_tests/`: Source Mapping + +Tests that exercise source code mapping. + +## `tests/ui/coercion/`: Type Coercion + +Tests for implicit type coercion behavior, where the types of some values are changed automatically when compatible depending on the context. E.g. automatic dereferencing or downgrading a `&mut` into a `&`. + +See [Type coercions | Reference](https://doc.rust-lang.org/reference/type-coercions.html). + +## `tests/ui/coherence/`: Trait Implementation Coherence + +Tests for trait coherence rules, which govern where trait implementations can be defined. E.g. orphan rule, and overlap checks. + +See [Coherence | rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/coherence.html#coherence). + +## `tests/ui/coinduction/`: Coinductive Trait Resolution + +Tests for coinduction in trait solving which may involve infinite proof trees. + +See: + +- [Coinduction | rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/solve/coinduction.html). +- [Inductive cycles | Chalk](https://rust-lang.github.io/chalk/book/recursive/inductive_cycles.html#inductive-cycles)/ + +This directory only contains one highly specific test. Other coinduction tests can be found down the deeply located `tests/ui/traits/next-solver/cycles/coinduction/` subdirectory. + +## `tests/ui/command/`: `std::process::Command` + +This directory is actually for the standard library [`std::process::Command`](https://doc.rust-lang.org/std/process/struct.Command.html) type, where some tests are too difficult or inconvenient to write as unit tests or integration tests within the standard library itself. + +**FIXME**: the test `command-line-diagnostics` seems to have been misplaced in this category. + +## `tests/ui/compare-method/`: Trait implementation and definition comparisons + +Some traits' implementation must be compared with their definition, checking for problems such as the implementation having stricter requirements (such as needing to implement `Copy`). + +This subdirectory is *not* intended comparison traits (`PartialEq`, `Eq`, `PartialOrd`, `Ord`). + +## `tests/ui/compiletest-self-test/`: compiletest "meta" tests + +Meta test suite of the test harness `compiletest` itself. + +## `tests/ui/conditional-compilation/`: Conditional Compilation + +Tests for `#[cfg]` attribute or `--cfg` flags, used to compile certain files or code blocks only if certain conditions are met (such as developing on a specific architecture). + +**FIXME**: There is significant overlap with `tests/ui/cfg`, which even contains a `tests/ui/cfg/conditional-compile.rs` test. Also investigate `tests/ui/check-cfg`. + +## `tests/ui/confuse-field-and-method/`: Field/Method Ambiguity + +If a developer tries to create a `struct` where one of the fields is a closure function, it becomes unclear whether `struct.field()` is accessing the field itself or trying to call the closure function within as a method. + +**FIXME**: does this really need to be its own immediate subdirectory? + +## `tests/ui/const-generics/`: Constant Generics + +Tests for const generics, allowing types to be parameterized by constant values. It is generally observed in the form `` after the `fn` or `struct` keywords. Includes tests for const expressions in generic contexts and associated type bounds. + +See: + +- [Tracking Issue for complex generic constants: `feature(generic_const_exprs)` #76560](https://github.com/rust-lang/rust/issues/76560) +- [Const generics | Reference](https://doc.rust-lang.org/reference/items/generics.html#const-generics) + +## `tests/ui/const_prop/`: Constant Propagation + +Tests exercising `ConstProp` mir-opt pass (mostly regression tests). See . + +## `tests/ui/const-ptr/`: Constant Pointers + +Tests exercise const raw pointers. E.g. pointer arithmetic, casting and dereferencing, always with a `const`. + +See: + +- [`std::primitive::pointer`](https://doc.rust-lang.org/std/primitive.pointer.html) +- [`std::ptr`](https://doc.rust-lang.org/std/ptr/index.html) +- [Pointer types | Reference](https://doc.rust-lang.org/reference/types/pointer.html) + +## `tests/ui/consts/`: General Constant Evaluation + +Anything to do with constants, which does not fit in the previous two `const` categories, goes here. This does not always imply use of the `const` keyword - other values considered constant, such as defining an enum variant as `enum Foo { Variant = 5 }` also counts. + +## `tests/ui/contracts/`: Contracts feature + +Tests exercising `#![feature(contracts)]`. + +See [Tracking Issue for Contracts #128044](https://github.com/rust-lang/rust/issues/128044). + +## `tests/ui/coroutine/`: Coroutines feature and `gen` blocks + +Tests for `#![feature(coroutines)]` and `gen` blocks, it belongs here. + +See: + +- [Coroutines | The Unstable book](https://doc.rust-lang.org/beta/unstable-book/language-features/coroutines.html) +- [RFC 3513 Gen blocks](https://rust-lang.github.io/rfcs/3513-gen-blocks.html) + +## `tests/ui/coverage-attr/`: `#[coverage]` attribute + +Tests for `#![feature(coverage_attribute)]`. See [Tracking issue for function attribute `#[coverage]`](https://github.com/rust-lang/rust/issues/84605). + +## `tests/ui/crate-loading/`: Crate Loading + +Tests for crate resolution and loading behavior, including `extern crate` declarations, `--extern` flags, or the `use` keyword. + +## `tests/ui/cross/`: Various tests related to the concept of "cross" + +**FIXME**: The unifying topic of these tests appears to be that their filenames begin with the word "cross". The similarities end there - one test is about "cross-borrowing" a `Box` into `&T`, while another is about a global trait used "across" files. Some of these terminology are really outdated and does not match the current terminology. Additionally, "cross" is also way too generic, it's easy to confuse with cross-compile. + +## `tests/ui/cross-crate/`: Cross-Crate Interaction + +Tests for behavior spanning multiple crates, including visibility rules, trait implementations, and type resolution across crate boundaries. + +## `tests/ui/custom_test_frameworks/` + +Tests for `#[bench]`, `#[test_case]` attributes and the `custom_test_frameworks` lang item. + +See [Tracking issue for eRFC 2318, Custom test frameworks #50297](https://github.com/rust-lang/rust/issues/50297). + +## `tests/ui/c-variadic/`: C Variadic Function + +Tests for FFI with C varargs (`va_list`). + +## `tests/ui/cycle-trait/`: Trait Cycle Detection + +Tests for detection and handling of cyclic trait dependencies. + +## `tests/ui/dataflow_const_prop/` + +Contains a single regression test for const prop in `SwitchInt` pass crashing when `ptr2int` transmute is involved. + +**FIXME**: A category with a single test. Maybe it would fit inside the category `const-prop` or some kind of `mir-opt` directory. + +## `tests/ui/debuginfo/` + +Tests for generation of debug information (DWARF, etc.) including variable locations, type information, and source line mapping. Also exercises `-C split-debuginfo` and `-C debuginfo`. + +## `tests/ui/definition-reachable/`: Definition Reachability + +Tests to check whether definitions are reachable. + +## `tests/ui/delegation/`: `#![feature(fn_delegation)]` + +Tests for `#![feature(fn_delegation)]`. See [Implement function delegation in rustc #3530](https://github.com/rust-lang/rfcs/pull/3530) for the proposed prototype experimentation. + +## `tests/ui/dep-graph/`: `-Z query-dep-graph` + +These tests use the unstable command line option `query-dep-graph` to examine the dependency graph of a Rust program, which is useful for debugging. + +## `tests/ui/deprecation/`: Deprecation Attribute + +Tests for `#[deprecated]` attribute and `deprecated_in_future` internal lint. + +## `tests/ui/deref-patterns/`: `#![feature(deref_patterns)]` and `#![feature(string_deref_patterns)]` + +Tests for `#![feature(deref_patterns)]` and `#![feature(string_deref_patterns)]`. See [Deref patterns | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/language-features/deref-patterns.html). + +**FIXME**: May have some overlap with `tests/ui/pattern/deref-patterns`. + +## `tests/ui/derived-errors/`: Derived Error Messages + +Tests for quality of diagnostics involving suppression of cascading errors in some cases to avoid overwhelming the user. + +## `tests/ui/derives/`: Derive Macro + +Tests for built-in derive macros (`Debug`, `Clone`, etc.) when used in conjunction with built-in `#[derive(..)]` attributes. + +## `tests/ui/deriving/`: Derive Macro + +**FIXME**: Coalesce with `tests/ui/derives`. + +## `tests/ui/dest-prop/` Destination Propagation + +**FIXME**: Contains a single test for the `DestProp` mir-opt, should probably be rehomed. + +## `tests/ui/destructuring-assignment/` + +Exercises destructuring assignments. See [RFC 2909 Destructuring assignment](https://github.com/rust-lang/rfcs/blob/master/text/2909-destructuring-assignment.md). + +## `tests/ui/diagnostic-flags/` + +These tests revolve around command-line flags which change the way error/warning diagnostics are emitted. For example, `--error-format=human --color=always`. + +**FIXME**: Check redundancy with `annotate-snippet`, which is another emitter. + +## `tests/ui/diagnostic_namespace/` + +Exercises `#[diagnostic::*]` namespaced attributes. See [RFC 3368 Diagnostic attribute namepsace](https://github.com/rust-lang/rfcs/blob/master/text/3368-diagnostic-attribute-namespace.md). + +## `tests/ui/diagnostic-width/`: `--diagnostic-width` + +Everything to do with `--diagnostic-width`. + +## `tests/ui/did_you_mean/` + +Tests for miscellaneous suggestions. + +## `tests/ui/directory_ownership/`: Declaring `mod` inside a block + +Exercises diagnostics for when a code block attempts to gain ownership of a non-inline module with a `mod` keyword placed inside of it. + +## `tests/ui/disallowed-deconstructing/`: Incorrect struct deconstruction + +Exercises diagnostics for disallowed struct destructuring. + +## `tests/ui/dollar-crate/`: `$crate` used with the `use` keyword + +There are a few rules - which are checked in this directory - to follow when using `$crate` - it must be used in the start of a `use` line and is a reserved identifier. + +**FIXME**: There are a few other tests in other directories with a filename starting with `dollar-crate`. They should perhaps be redirected here. + +## `tests/ui/drop/`: `Drop` and drop order + +Not necessarily about `Drop` and its implementation, but also about the drop order of fields inside a struct. + +## `tests/ui/drop-bounds/` + +Tests for linting on bounding a generic type on `Drop`. + +## `tests/ui/dropck/`: Drop Checking + +Mostly about checking the validity of `Drop` implementations. + +See: + +- [Dropck | The Nomicon](https://doc.rust-lang.org/nomicon/dropck.html) +- [Drop check | rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/borrow_check/drop_check.html) + +## `tests/ui/dst/`: Dynamically Sized Types + +Tests for dynamically-sized types (DSTs). See [Dynamically Sized Types | Reference](https://doc.rust-lang.org/reference/dynamically-sized-types.html). + +## `tests/ui/duplicate/`: Duplicate Symbols + +Tests about duplicated symbol names and associated errors, such as using the `#[export_name]` attribute to rename a function with the same name as another function. + +## `tests/ui/dynamically-sized-types/`: Dynamically Sized Types + +**FIXME**: should be coalesced with `tests/ui/dst`. + +## `tests/ui/dyn-compatibility/`: Dyn-compatibility + +Tests for dyn-compatibility of traits. + +See: + +- [Trait object | Reference](https://doc.rust-lang.org/reference/types/trait-object.html) +- [Dyn compatibility | Reference](https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility) + +Previously known as "object safety". + +## `tests/ui/dyn-drop/`: `dyn Drop` + +**FIXME**: Contains a single test, used only to check the `dyn_drop` lint (which is normally `warn` level). + +## `tests/ui/dyn-keyword/`: `dyn` and Dynamic Dispatch + +The `dyn` keyword is used to highlight that calls to methods on the associated Trait are dynamically dispatched. To use the trait this way, it must be dyn-compatible - tests about dyn-compatibility belong in `tests/ui/dyn-compatibility/`, while more general tests on dynamic dispatch belong here. + +See [`dyn` keyword](https://doc.rust-lang.org/std/keyword.dyn.html). + +## `tests/ui/dyn-star/`: `dyn*`, Sized `dyn`, `#![feature(dyn_star)]` + +See [Tracking issue for dyn-star #102425](https://github.com/rust-lang/rust/issues/102425). + +## `tests/ui/editions/`: Rust edition-specific peculiarities + +These tests run in specific Rust editions, such as Rust 2015 or Rust 2018, and check errors and functionality related to specific now-deprecated idioms and features. + +**FIXME**: Maybe regroup `rust-2018`, `rust-2021` and `rust-2024` under this umbrella? + +## `tests/ui/empty/`: Various tests related to the concept of "empty" + +**FIXME**: These tests need better homes, this is not very informative. + +## `tests/ui/entry-point/`: `main` function + +Tests exercising the `main` entry-point. + +## `tests/ui/enum/` + +General-purpose tests on `enum`s. See [Enumerations | Reference](https://doc.rust-lang.org/reference/items/enumerations.html). + +## `tests/ui/enum-discriminant/` + +`enum` variants can be differentiated independently of their potential field contents with `discriminant`, which returns the type `Discriminant`. See [`std::mem::discriminant`](https://doc.rust-lang.org/std/mem/fn.discriminant.html). + +## `tests/ui/env-macro/`: `env!` + +Exercises `env!` and `option_env!` macros. + +## `tests/ui/ergonomic-clones/` + +See [RFC 3680 Ergonomic clones](https://github.com/rust-lang/rfcs/pull/3680). + +## `tests/ui/error-codes/`: Error codes + +Tests for errors with dedicated error codes. + +## `tests/ui/error-emitter/` + +Quite similar to `ui/diagnostic-flags` in some of its tests, this category checks some behaviours of Rust's error emitter into the user's terminal window, such as truncating error in the case of an excessive amount of them. + +## `tests/ui/errors/` + +These tests are about very different topics, only unified by the fact that they result in errors. + +**FIXME**: "Errors" is way too generic, the tests probably need to be rehomed into more descriptive subdirectories. + +## `tests/ui/explain/`: `rustc --explain EXXXX` + +Accompanies `tests/ui/error-codes/`, exercises the `--explain` cli flag. + +## `tests/ui/explicit/`: Errors involving the concept of "explicit" + +This category contains three tests: two which are about the specific error `explicit use of destructor method`, and one which is about explicit annotation of lifetimes: https://doc.rust-lang.org/stable/rust-by-example/scope/lifetime/explicit.html. + +**FIXME**: Rehome the two tests about the destructor method with `drop`-related categories, and rehome the last test with a category related to lifetimes. + +## `tests/ui/explicit-tail-calls/` + +Exercises `#![feature(explicit_tail_calls)]` and the `become` keyword. See [Explicit Tail Calls #3407](https://github.com/rust-lang/rfcs/pull/3407). + +## `tests/ui/expr/`: Expressions + +A broad directory for tests on expressions. + +## `tests/ui/extern/` + +Tests on the `extern` keyword and `extern` blocks and functions. + +## `tests/ui/extern-flag/`: `--extern` command line flag + +Tests for the `--extern` CLI flag. + +## `tests/ui/feature-gates/` + +Tests on feature-gating, and the `#![feature(..)]` mechanism itself. + +## `tests/ui/ffi-attrs/`: `#![feature(ffi_const, ffi_pure)]` + +The `#[ffi_const]` and `#[ffi_pure]` attributes applies clang's `const` and `pure` attributes to foreign functions declarations, respectively. These attributes are the core element of the tests in this category. + +See: + +- [`ffi_const` | The Unstable book](https://doc.rust-lang.org/unstable-book/language-features/ffi-const.html) +- [`ffi_pure` | The Unstable book](https://doc.rust-lang.org/beta/unstable-book/language-features/ffi-pure.html) + +## `tests/ui/fmt/` + +Exercises the `format!` macro. + +## `tests/ui/fn/` + +A broad category of tests on functions. + +## `tests/ui/fn-main/` + +**FIXME**: Serves a duplicate purpose with `ui/entry-point`, should be combined. + +## `tests/ui/for/`: `for` keyword + +Tests on the `for` keyword and some of its associated errors, such as attempting to write the faulty pattern `for _ in 0..1 {} else {}`. + +**FIXME**: Should be merged with `ui/for-loop-while`. + +## `tests/ui/force-inlining/`: `#[rustc_force_inline]` + +Tests for `#[rustc_force_inline]`, which will force a function to always be labelled as inline by the compiler (it will be inserted at the point of its call instead of being used as a normal function call.) If the compiler is unable to inline the function, an error will be reported. See . + +## `tests/ui/foreign/`: Foreign Function Interface (FFI) + +Tests for `extern "C"` and `extern "Rust`. + +**FIXME**: Check for potential overlap/merge with `ui/c-variadic` and/or `ui/extern`. + +## `tests/ui/for-loop-while/` + +Anything to do with loops and `for`, `loop` and `while` keywords to express them. + +**FIXME**: After `ui/for` is merged into this, also carry over its SUMMARY text. + +## `tests/ui/frontmatter/` + +Tests for `#![feature(frontmatter)]`. See [Tracking Issue for `frontmatter` #136889](https://github.com/rust-lang/rust/issues/136889). + +## `tests/ui/fully-qualified-type/` + +Tests for diagnostics when there may be identically named types that need further qualifications to disambiguate. + +## `tests/ui/functional-struct-update/` + +Functional Struct Update is the name for the idiom by which one can write `..` at the end of a struct literal expression to fill in all remaining fields of the struct literal by using `` as the source for them. + +See [RFC 0736 Privacy-respecting Functional Struct Update](https://github.com/rust-lang/rfcs/blob/master/text/0736-privacy-respecting-fru.md). + +## `tests/ui/function-pointer/` + +Tests on function pointers, such as testing their compatibility with higher-ranked trait bounds. + +See: + +- [Function pointer types | Reference](https://doc.rust-lang.org/reference/types/function-pointer.html) +- [Higher-ranked trait bounds | Nomicon](https://doc.rust-lang.org/nomicon/hrtb.html) + +## `tests/ui/functions-closures/` + +Tests on closures. See [Closure expressions | Reference](https://doc.rust-lang.org/reference/expressions/closure-expr.html). + +## `tests/ui/generic-associated-types/` + +Tests on Generic Associated Types (GATs). + +## `tests/ui/generic-const-items/` + +Tests for `#![feature(generic_const_items)]`. See [Tracking issue for generic const items #113521](https://github.com/rust-lang/rust/issues/113521). + +## `tests/ui/generics/` + +A broad category of tests on generics, usually used when no more specific subdirectories are fitting. + +## `tests/ui/half-open-range-patterns/`: `x..` or `..x` range patterns + +Tests on range patterns where one of the bounds is not a direct value. + +**FIXME**: Overlaps with `ui/range`. `impossible_range.rs` is particularly suspected to be a duplicate test. + +## `tests/ui/hashmap/` + +Tests for the standard library collection [`std::collections::HashMap`](https://doc.rust-lang.org/std/collections/struct.HashMap.html). + +## `tests/ui/hello_world/` + +Tests that the basic hello-world program is not somehow broken. + +## `tests/ui/higher-ranked/` + +Tests for higher-ranked trait bounds. + +See: + +- [Higher-ranked trait bounds | rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/traits/hrtb.html) +- [Higher-ranked trait bounds | Nomicon](https://doc.rust-lang.org/nomicon/hrtb.html) + +## `tests/ui/hygiene/` + +This seems to have been originally intended for "hygienic macros" - macros which work in all contexts, independent of what surrounds them. However, this category has grown into a mish-mash of many tests that may belong in the other directories. + +**FIXME**: Reorganize this directory properly. + +## `tests/ui/illegal-sized-bound/` + +This test category revolves around trait objects with `Sized` having illegal operations performed on them. + +**FIXME**: There seems to be unrelated testing in this directory, such as `tests/ui/illegal-sized-bound/mutability-mismatch-arg.rs`. Investigate. + +## `tests/ui/impl-header-lifetime-elision/` + +Tests on lifetime elision in impl function signatures. See [Lifetime elision | Nomicon](https://doc.rust-lang.org/nomicon/lifetime-elision.html). + +## `tests/ui/implied-bounds/` + +See [Implied bounds | Reference](https://doc.rust-lang.org/reference/trait-bounds.html#implied-bounds). + +## `tests/ui/impl-trait/` + +Tests for trait impls. + +## `tests/ui/imports/` + +Tests for module system and imports. + +## `tests/ui/include-macros/` + +Exercise `include!`, `include_str!`, and `include_bytes!` macros. + +## `tests/ui/incoherent-inherent-impls/` + +Exercise forbidding inherent impls on a type defined in a different crate. + +## `tests/ui/indexing/` + +Tests on collection types (arrays, slices, vectors) and various errors encountered when indexing their contents, such as accessing out-of-bounds values. + +**FIXME**: (low-priority) could maybe be a subdirectory of `ui/array-slice-vec` + +## `tests/ui/inference/` + +Tests on type inference. + +## `tests/ui/infinite/` + +Tests for diagnostics on infinitely recursive types without indirection. + +## `tests/ui/inherent-impls-overlap-check/` + +Checks that repeating the same function names across separate `impl` blocks triggers an informative error, but not if the `impl` are for different types, such as `Bar` and `Bar`. + +NOTE: This should maybe be a subdirectory within another related to duplicate definitions, such as `tests/ui/duplicate/`. + +## `tests/ui/inline-const/` + +These tests revolve around the inline `const` block that forces the compiler to const-eval its content. + +## `tests/ui/instrument-coverage/`: `-Cinstrument-coverage` command line flag + +See [Instrument coverage | The rustc book](https://doc.rust-lang.org/rustc/instrument-coverage.html). + +## `tests/ui/instrument-xray/`: `-Z instrument-xray` + +See [Tracking issue for `-Z instrument-xray` #102921](https://github.com/rust-lang/rust/issues/102921). + +## `tests/ui/interior-mutability/` + +**FIXME**: contains a single test, probably better rehomed. + +## `tests/ui/internal/` + +Tests for `internal_unstable` and the attribute header `#![feature(allow_internal_unstable)]`, which lets compiler developers mark features as internal to the compiler, and unstable for standard library use. + +## `tests/ui/internal-lints/` + +Tests for rustc-internal lints. + +## `tests/ui/intrinsics/` + +Tests for the `{std,core}::intrinsics`, internal implementation detail. + +## `tests/ui/invalid/` + +Various tests related to rejecting invalid inputs. + +**FIXME**: This is rather uninformative, possibly rehome into more meaningful directories. + +## `tests/ui/invalid-compile-flags/` + +Tests for checking that invalid usage of compiler flags are rejected. + +## `tests/ui/invalid-module-declaration/` + +**FIXME**: Consider merging into module/resolve directories. + +## `tests/ui/invalid-self-argument/`: `self` as a function argument incorrectly + +Tests with erroneous ways of using `self`, such as having it not be the first argument, or using it in a non-associated function (no `impl` or `trait`). + +**FIXME**: Maybe merge with `ui/self`. + +## `tests/ui/io-checks/` + +Contains a single test. The test tries to output a file into an invalid directory with `-o`, then checks that the result is an error, not an internal compiler error. + +**FIXME**: Rehome to invalid compiler flags maybe. + +## `tests/ui/issues/`: Tests directly related to GitHub issues + +**FIXME (#133895)**: Random collection of regression tests and tests for issues, tests in this directory should be audited and rehomed. + +## `tests/ui/iterators/` + +These tests revolve around anything to do with iterators, e.g. mismatched types. + +**FIXME**: Check for potential overlap with `ui/for-loop-while`. + +## `tests/ui/json/` + +These tests revolve around the `--json` compiler flag. See [JSON Output](https://doc.rust-lang.org/rustc/json.html#json-output). + +## `tests/ui/keyword/` + +Tests exercising keywords, such as attempting to use them as identifiers when not contextual keywords. + +## `tests/ui/kindck/` + +**FIXME**: `kindck` is no longer a thing, these tests probably need to be audited and rehomed. + +## `tests/ui/label/` + +Exercises block and loop `'label`s. + +## `tests/ui/lang-items/` + +See [Lang items | The Unstable book](https://doc.rust-lang.org/unstable-book/language-features/lang-items.html). + +## `tests/ui/late-bound-lifetimes/` + +See [Early vs Late bound parameters | rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/early_late_parameters.html#early-vs-late-bound-parameters). + +## `tests/ui/layout/` + +See [Type Layout | Reference](https://doc.rust-lang.org/reference/type-layout.html). + +## `tests/ui/lazy-type-alias/` + +Tests for `#![feature(lazy_type_alias)]`. See [Tracking issue for lazy type aliases #112792 +](https://github.com/rust-lang/rust/issues/112792). + +## `tests/ui/lazy-type-alias-impl-trait/` + +This feature allows use of an `impl Trait` in multiple locations while actually using the same concrete type (`type Alias = impl Trait;`) everywhere, keeping the original `impl Trait` hidden. + +**FIXME**: merge this with `tests/ui/type-alias-impl-trait/`? + +## `tests/ui/let-else/` + +Exercises let-else constructs. + +## `tests/ui/lexer/` + +Exercises of the lexer. + +## `tests/ui/lifetimes/` + +Broad directory on lifetimes, including proper specifiers, lifetimes not living long enough, or undeclared lifetime names. + +## `tests/ui/limits/` + +These tests exercises numerical limits, such as `[[u8; 1518599999]; 1518600000]`. + +## `tests/ui/linkage-attr/` + +Tests for the linkage attribute `#[linkage]` of `#![feature(linkage)]`. + +**FIXME**: Some of these tests do not use the feature at all, which should be moved under `ui/linking` instead. + +## `tests/ui/linking/` + +Tests on code which fails during the linking stage, or which contain arguments and lines that have been known to cause unjustified errors in the past, such as specifying an unusual `#[export_name]`. + +See [Linkage | Reference](https://doc.rust-lang.org/reference/linkage.html). + +## `tests/ui/link-native-libs/` + +Tests for `#[link(name = "", kind = "")]` and `-l` command line flag. + +See [Tracking Issue for linking modifiers for native libraries #81490](https://github.com/rust-lang/rust/issues/81490). + +## `tests/ui/lint/` + +Tests for the lint infrastructure, lint levels, lint reasons, etc. + +See: + +- [Lints | The rustc book](https://doc.rust-lang.org/rustc/lints/index.html) +- [Lint reasons | Reference](https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-reasons) + +## `tests/ui/liveness/` + +Tests exercising analysis for unused variables, unreachable statements, functions which are supposed to return a value but do not, as well as values moved elsewhere before they could be used by a function. + +**FIXME**: This seems unrelated to "liveness" as defined in the rustc compiler guide. Is this misleadingly named? https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/lifetime_parameters.html#liveness-and-universal-regions + +## `tests/ui/loops/` + +Tests on the `loop` construct. + +**FIXME**: Consider merging with `ui/for-loop-while`. + +## `tests/ui/lowering/` + +Tests on [AST lowering](https://rustc-dev-guide.rust-lang.org/ast-lowering.html). + +## `tests/ui/lto/` + +Exercise *Link-Time Optimization* (LTO), involving the flags `-C lto` or `-Z thinlto`. + +## `tests/ui/lub-glb/`: LUB/GLB algorithm update + +Tests on changes to inference variable lattice LUB/GLB, see . + +## `tests/ui/macro_backtrace/`: `-Zmacro-backtrace` + +Contains a single test, checking the unstable command-line flag to enable detailed macro backtraces. + +**FIXME**: This could be merged with `ui/macros`, which already contains other macro backtrace tests. + +## `tests/ui/macros/` + +Broad category of tests on macros. + +## `tests/ui/malformed/` + +Broad category of tests on malformed inputs. + +**FIXME**: this is kinda vague, probably best to audit and rehome tests. + +## `tests/ui/marker_trait_attr/` + +See [Tracking issue for allowing overlapping implementations for marker trait #29864](https://github.com/rust-lang/rust/issues/29864). + +## `tests/ui/match/` + +Broad category of tests on `match` constructs. + +## `tests/ui/meta/`: Tests for compiletest itself + +These tests check the function of the UI test suite at large and Compiletest in itself. + +**FIXME**: This should absolutely be merged with `tests/ui/compiletest-self-test/`. + +## `tests/ui/methods/` + +A broad category for anything related to methods and method resolution. + +## `tests/ui/mir/` + +Certain mir-opt regression tests. + +## `tests/ui/mir-dataflow` + +Tests for MIR dataflow analysis. + +See [MIR Dataflow | rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/mir/dataflow.html). + +## `tests/ui/mismatched_types/` + +Exercises on mismatched type diagnostics. + +## `tests/ui/missing/` + +Something is missing which could be added to fix (e.g. suggestions). + +**FIXME**: this is way too vague, tests should be rehomed. + +## `tests/ui/missing_non_modrs_mod/` + +This directory is a small tree of `mod` dependencies, but the root, `foo.rs`, is looking for a file which does not exist. The test checks that the error is reported at the top-level module. + +**FIXME**: Merge with `tests/ui/modules/`. + +## `tests/ui/missing-trait-bounds/` + +Tests for checking missing trait bounds, and their diagnostics. + +**FIMXE**: Maybe a subdirectory of `ui/trait-bounds` would be more appropriate. + +## `tests/ui/modules/` + +Tests on the module system. + +**FIXME**: `tests/ui/imports/` should probably be merged with this. + +## `tests/ui/modules_and_files_visibility/` + +**FIXME**: Merge with `tests/ui/modules/`. + +## `tests/ui/moves` + +Tests on moves (destructive moves). + +## `tests/ui/mut/` + +Broad category of tests on mutability, such as the `mut` keyword, borrowing a value as both immutable and mutable (and the associated error), or adding mutable references to `const` declarations. + +## `tests/ui/namespace/` + +Contains a single test. It imports a massive amount of very similar types from a crate, then attempts various permutations of their namespace paths, checking for errors or the lackthereof. + +**FIXME**: Move under either `tests/ui/modules/` or `tests/ui/resolve/`. + +## `tests/ui/never_type/` + +See [Tracking issue for promoting `!` to a type (RFC 1216) #35121](https://github.com/rust-lang/rust/issues/35121). + +## `tests/ui/new-range/` + +See [RFC 3550 New Range](https://github.com/rust-lang/rfcs/blob/master/text/3550-new-range.md). + +## `tests/ui/nll/`: Non-lexical lifetimes + +Tests for Non-lexical lifetimes. See [RFC 2094 NLL](https://rust-lang.github.io/rfcs/2094-nll.html). + +## `tests/ui/non_modrs_mods/` + +Despite the size of the directory, this is a single test, spawning a sprawling `mod` dependency tree and checking its successful build. + +**FIXME**: Consider merge with `tests/ui/modules/`, keeping the directory structure. + +## `tests/ui/non_modrs_mods_and_inline_mods/` + +A very similar principle as `non_modrs_mods`, but with an added inline `mod` statement inside another `mod`'s code block. + +**FXIME**: Consider merge with `tests/ui/modules/`, keeping the directory structure. + +## `tests/ui/no_std/` + +Tests for where the standard library is disabled through `#![no_std]`. + +## `tests/ui/not-panic/` + +Tests checking various types, such as `&RefCell`, and whether they are not `UnwindSafe` as expected. + +## `tests/ui/numbers-arithmetic/` + +Tests that exercises edge cases, such as specific floats, large or very small numbers, or bit conversion, and check that the arithmetic results are as expected. + +## `tests/ui/numeric/` + +Tests that checks numeric types and their interactions, such as casting among them with `as` or providing the wrong numeric suffix. + +## `tests/ui/object-lifetime/` + +Tests on lifetimes on objects, such as a lifetime bound not being able to be deduced from context, or checking that lifetimes are inherited properly. + +**FIXME**: Just a more specific subset of `ui/lifetimes`. + +## `tests/ui/obsolete-in-place/` + +Contains a single test. Check that we reject the ancient Rust syntax `x <- y` and `in(BINDING) {}` construct. + +**FIXME**: Definitely should be rehomed, maybe to `tests/ui/deprecation/`. + +## `tests/ui/offset-of/` + +Exercises the [`std::mem::offset_of` macro](https://doc.rust-lang.org/beta/std/mem/macro.offset_of.html). + +## `tests/ui/on-unimplemented/` + +Exercises the `#[rustc_on_unimplemented]`. + +## `tests/ui/operator-recovery/` + +**FIXME**: Probably move under `tests/ui/binop/` or `tests/ui/parser/`. + +## `tests/ui/or-patterns/` + +Exercises `||` and `|` in patterns. + +## `tests/ui/overloaded/` + +Exercises operator overloading via [`std::ops`](https://doc.rust-lang.org/std/ops/index.html). + +## `tests/ui/packed/` + +See [`repr(packed)` | Nomicon](https://doc.rust-lang.org/nomicon/other-reprs.html#reprpacked-reprpackedn). + +## `tests/ui/panic-handler/` + +See [panic handler | Nomicon](https://doc.rust-lang.org/nomicon/panic-handler.html). + +## `tests/ui/panic-runtime/` + +Exercises `#![panic_runtime]`, `-C panic`, panic runtimes and panic unwind strategy. + +See [RFC 1513 Less unwinding](https://github.com/rust-lang/rfcs/blob/master/text/1513-less-unwinding.md). + +## `tests/ui/panics/` + +Broad category of tests about panics in general, often but not necessarily using the `panic!` macro. + +## `tests/ui/parallel-rustc/` + +Efforts towards a [Parallel Rustc Front-end](https://github.com/rust-lang/rust/issues/113349). Includes `-Zthreads=`. + +## `tests/ui/parser/` + +Various parser tests + +**FIXME**: Maybe move `tests/ui/keywords/` under this? + +## `tests/ui/patchable-function-entry/` + +See [Patchable function entry | The Unstable book](https://doc.rust-lang.org/unstable-book/compiler-flags/patchable-function-entry.html). + +## `tests/ui/pattern/` + +Broad category of tests surrounding patterns. See [Patterns | Reference](https://doc.rust-lang.org/reference/patterns.html). + +**FIXME**: Some overlap with `tests/ui/match/`. + +## `tests/ui/pin-macro/` + +See [`std::pin`](https://doc.rust-lang.org/std/pin/). + +## `tests/ui/precondition-checks/` + +Exercises on some unsafe precondition checks. + +## `tests/ui/print-request/` + +Tests on `--print` compiler flag. See [print options | The rustc book](https://doc.rust-lang.org/rustc/command-line-arguments/print-options.html). + +## `tests/ui/print_type_sizes/` + +Exercises the `-Z print-type-sizes` flag. + +## `tests/ui/privacy/` + +Exercises on name privacy. E.g. the meaning of `pub`, `pub(crate)`, etc. + +## `tests/ui/process/` + +Some standard library process tests which are hard to write within standard library crate tests. + +## `tests/ui/process-termination/` + +Some standard library process termination tests which are hard to write within standard library crate tests. + +## `tests/ui/proc-macro/` + +Broad category of tests on proc-macros. See [Procedural Macros | Reference](https://doc.rust-lang.org/reference/procedural-macros.html). + +## `tests/ui/ptr_ops/`: Using operations on a pointer + +Contains only 2 tests, related to a single issue, which was about an error caused by using addition on a pointer to `i8`. + +**FIXME**: Probably rehome under some typecheck / binop directory. + +## `tests/ui/pub/`: `pub` keyword + +A large category about function and type public/private visibility, and its impact when using features across crates. Checks both visibility-related error messages and previously buggy cases. + +**FIXME**: merge with `tests/ui/privacy/`. + +## `tests/ui/qualified/` + +Contains few tests on qualified paths where a type parameter is provided at the end: `type A = ::A::f;`. The tests check if this fails during type checking, not parsing. + +**FIXME**: Should be rehomed to `ui/typeck`. + +## `tests/ui/query-system/` + +Tests on Rust methods and functions which use the query system, such as `std::mem::size_of`. These compute information about the current runtime and return it. See [Query system | rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/query.html). + +## `tests/ui/range/` + +Broad category of tests ranges, both in their `..` or `..=` form, as well as the standard library `Range`, `RangeTo`, `RangeFrom` or `RangeBounds` types. + +**FIXME**: May have some duplicate tests with `ui/new-range`. + +## `tests/ui/raw-ref-op/`: Using operators on `&raw` values + +Exercises `&raw mut ` and `&raw const `. See [RFC 2582 Raw reference MIR operator](https://github.com/rust-lang/rfcs/blob/master/text/2582-raw-reference-mir-operator.md). + +## `tests/ui/reachable` + +Reachability tests, primarily unreachable code and coercions into the never type `!` from diverging expressions. + +**FIXME**: Check for overlap with `ui/liveness`. + +## `tests/ui/recursion/` + +Broad category of tests exercising recursions (compile test and run time), in functions, macros, `type` definitions, and more. + +Also exercises the `#![recursion_limit = ""]` attribute. + +## `tests/ui/recursion_limit/`: `#![recursion_limit = ""]` + +Sets a recursion limit on recursive code. + +**FIXME**: Should be merged with `tests/ui/recursion/`. + +## `tests/ui/regions/` + +**FIXME**: Maybe merge with `ui/lifetimes`. + +## `tests/ui/repeat-expr/` + +Exercises `[Type; n]` syntax for creating arrays with repeated types across a set size. + +**FIXME**: Maybe make this a subdirectory of `ui/array-slice-vec`. + +## `tests/ui/repr/`: `#[repr(_)]` + +Tests on the `#[repr(..)]` attribute. See [Representations | Reference](https://doc.rust-lang.org/reference/type-layout.html#representations). + +## `tests/ui/reserved/` + +Reserved keywords and attribute names. + +See e.g. [Reserved keywords | Reference](https://doc.rust-lang.org/reference/keywords.html). + +**FIXME**: maybe merge under `tests/ui/keyword/`. + +## `tests/ui/resolve/`: Name resolution + +See [Name resolution | rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/name-resolution.html). + +## `tests/ui/return/` + +Exercises the `return` keyword, return expressions and statements. + +## `tests/ui/rfcs/` + +Tests that accompanies an implementation for an RFC. + +## `tests/ui/rmeta/` + +Exercises `.rmeta` crate metadata and the `--emit=metadata` cli flag. + +## `tests/ui/runtime/` + +Tests for runtime environment on which Rust programs are executed. E.g. Unix `SIGPIPE`. + +## `tests/ui/rust-{2018,2021,2024}/` + +Tests that exercise behaviors and features that are specific to editions. + +## `tests/ui/rustc-env` + +Tests on environmental variables that affect `rustc`. + +## `tests/ui/rustdoc` + +Hybrid tests that exercises `rustdoc`, and also some joint `rustdoc`/`rustc` interactions. + +## `tests/ui/sanitizer/` + +Exercises sanitizer support. See [Sanitizer | The rustc book](https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html). + +## `tests/ui/self/`: `self` keyword + +Tests with erroneous ways of using `self`, such as using `this.x` syntax as seen in other languages, having it not be the first argument, or using it in a non-associated function (no `impl` or `trait`). It also contains correct uses of `self` which have previously been observed to cause ICEs. + +## `tests/ui/sepcomp/`: Separate Compilation + +In this directory, multiple crates are compiled, but some of them have `inline` functions, meaning they must be inlined into a different crate despite having been compiled separately. + +**FIXME**: this directory might need some better docs, also this directory might want a better name. + +## `tests/ui/shadowed/` + +Tests on name shadowing. + +## `tests/ui/shell-argfiles/`: `-Z shell-argfiles` command line flag + +The `-Zshell-argfiles` compiler flag allows argfiles to be parsed using POSIX "shell-style" quoting. When enabled, the compiler will use shlex to parse the arguments from argfiles specified with `@shell:`. + +Because this feature controls the parsing of input arguments, the `-Zshell-argfiles` flag must be present before the argument specifying the shell-style argument file. + +**FIXME**: maybe group this with `tests/ui/argfile/` + +## `tests/ui/simd/` + +Some tests exercising SIMD support. + +## `tests/ui/single-use-lifetime/` + +This is a test directory for the specific error case where a lifetime never gets used beyond a single annotation on, for example, a `struct`. + +## `tests/ui/sized/`: `Sized` trait, sized types + +While many tests here involve the `Sized` trait directly, some instead test, for example the slight variations between returning a zero-sized `Vec` and a `Vec` with one item, where one has no known type and the other does. + +## `tests/ui/span/` + +An assorted collection of tests that involves specific diagnostic spans. + +**FIXME**: This is a big directory with numerous only-tangentially related tests. Maybe some moving is in order. + +## `tests/ui/specialization` + +See [Tracking issue for specialization (RFC 1210) #31844](https://github.com/rust-lang/rust/issues/31844). + +## `tests/ui/stability-attribute/` + +Stability attributes used internally by the standard library: `#[stable()]` and `#[unstable()]`. + +## `tests/ui/stable-mir-print/` + +Some tests for pretty printing of StableMIR. + +## `tests/ui/stack-protector/`: `-Z stack-protector` command line flag + +See [Tracking Issue for stabilizing stack smashing protection (i.e., `-Z stack-protector`) #114903](https://github.com/rust-lang/rust/issues/114903). + +## `tests/ui/static/` + +Tests on static items. + +## `tests/ui/statics/` + +**FIXME**: should probably be merged with `tests/ui/static/`. + +## `tests/ui/stats/` + +Tests for compiler-internal stats; `-Z meta-stats` and `-Z input-stats` flags. + +## `tests/ui/std/`: Tests which use features from the standard library + +A catch-all category about anything that can come from `std`. + +**FIXME**: this directory is probably too vague, tests might need to be audited and rehomed. + +## `tests/ui/stdlib-unit-tests/` + +Some standard library tests which are too inconvenient or annoying to implement as std crate tests. + +## `tests/ui/str/` + +Exercise `str` keyword and string slices. + +## `tests/ui/structs/` + +Assorted tests surrounding the `struct` keyword, struct type definitions and usages. + +## `tests/ui/structs-enums/` + +Tests on both structs and enums. + +**FIXME**: maybe coalesce {`tests/ui/structs/`, `tests/ui/structs-enums/`, `tests/ui/enums/`} into one `tests/ui/adts` directory... + +## `tests/ui/suggestions/` + +Generic collection of tests for suggestions, when no more specific directories are applicable. + +**FIXME**: Some overlap with `tests/ui/did_you_mean/`, that directory should probably be moved under here. + +## `tests/ui/svh/`: Strict Version Hash + +Tests on the *Strict Version Hash* (SVH, also known as the "crate hash"). + +See [Strict Version Hash](https://rustc-dev-guide.rust-lang.org/backend/libs-and-metadata.html#strict-version-hash). + +## `tests/ui/symbol-mangling-version/`: `-Csymbol-mangling-version` command line flag + +**FIXME**: Should be merged with `ui/symbol-names`. + +## `tests/ui/symbol-names/`: Symbol mangling and related attributes + +These tests revolve around `#[no_mangle]` attribute, as well as consistently mangled symbol names (checked with the `rustc_symbol_name` attribute), which is important to build reproducible binaries. + +## `tests/ui/sync/`: `Sync` trait + +Exercises `Sync` trait and auto-derive thereof. + +## `tests/ui/target-cpu/`: `-C target-cpu` command line flag + +This command line option instructs rustc to generate code specifically for a particular processor. + +**FIXME**: Contains a single test, maybe put it in a directory about misc codegen options? + +## `tests/ui/target-feature/`: `#[target_feature(enable = "relaxed-simd")]` + +Exercises the `#[target_feature(..)]` attribute. See [Target feature attribute | Reference](https://doc.rust-lang.org/reference/attributes/codegen.html#the-target_feature-attribute). + +## `tests/ui/target_modifiers/` + +Tests for [RFC 3716: Target Modifiers](https://github.com/rust-lang/rfcs/pull/3716). + +See [Tracking Issue for target modifiers #136966](https://github.com/rust-lang/rust/issues/136966). + +## `tests/ui/test-attrs/` + +Exercises the [`#[test]` attribute](https://doc.rust-lang.org/reference/attributes/testing.html#testing-attributes). + +## `tests/ui/thir-print/` + +Pretty print of THIR trees via `-Zunpretty=thir-tree`. + +## `tests/ui/thread-local/` + +Exercises thread local values and `#[thread_local]` attribute. + +See [Tracking issue for thread_local stabilization #29594](https://github.com/rust-lang/rust/issues/29594). + +## `tests/ui/threads-sendsync/` + +Broad category for parallelism and multi-threaded tests, including attempting to send types across threads which are not thread-safe. + +## `tests/ui/tool-attributes/`: External tool attributes + +Exercises [tool attributes](https://doc.rust-lang.org/reference/attributes.html#tool-attributes). + +## `tests/ui/track-diagnostics/` + +Exercises `#[track_caller]` and `-Z track-diagnostics`. + +## `tests/ui/trait-bounds/` + +Collection of tests for [trait bounds](https://doc.rust-lang.org/reference/trait-bounds.html). + +## `tests/ui/traits/` + +Broad collection of tests on traits in general. + +**FIXME**: This could be better organized in subdirectories containing tests such as `ui/traits/trait-bounds`. + +## `tests/ui/transmutability/`: `#![feature(transmutability)]` + +See [Tracking Issue for Transmutability Trait: `#[transmutability]` #99571](https://github.com/rust-lang/rust/issues/99571). + +See also [Project Safe Transmute](https://github.com/rust-lang/project-safe-transmute). + +## `tests/ui/transmute/` + +Tests surrounding [`std::mem::transmute`](https://doc.rust-lang.org/std/mem/fn.transmute.html). + +## `tests/ui/treat-err-as-bug/` + +Exercises compiler development support flag `-Z treat-err-as-bug`. + +## `tests/ui/trivial-bounds/` + +`#![feature(trivial_bounds)]`. See [RFC 2056 Allow trivial where clause constraints](https://github.com/rust-lang/rfcs/blob/master/text/2056-allow-trivial-where-clause-constraints.md). + +## `tests/ui/try-block/` + +`#![feature(try_blocks)]`. See [Tracking issue for `?` operator and `try` blocks (RFC 243, `question_mark` & `try_blocks` features)](https://github.com/rust-lang/rust/issues/31436). + +## `tests/ui/try-trait/` + +`#![feature(try_trait_v2)]`. See [RFC 3058 Try Trait v2](https://github.com/rust-lang/rfcs/blob/master/text/3058-try-trait-v2.md). + +## `tests/ui/tuple/` + +Tests surrounding the tuple type `()`. + +## `tests/ui/type/` + +Assorted collection of tests surrounding the concept of a "type". + +**FIXME**: There is very little consistency across tests of this category, and should probably be sent to other subdirectories. + +## `tests/ui/type-alias/` + +Exercises [type aliases](https://doc.rust-lang.org/reference/items/type-aliases.html). + +## `tests/ui/type-alias-enum-variants/` + +Tests for `type` aliases in the context of `enum` variants, such as that applied type arguments of enums are respected independently of being the original type or the `type` alias. + +## `tests/ui/type-alias-impl-trait/` + +`#![feature(type_alias_impl_trait)]`. See [Type Alias Impl Trait | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/language-features/type-alias-impl-trait.html). + +## `tests/ui/typeck/` + +General collection of type checking related tests. + +## `tests/ui/type-inference/` + +General collection of type inference related tests. + +## `tests/ui/typeof/` + +`typeof` keyword, reserved but unimplemented. + +## `tests/ui/ufcs/` + +See [RFC 0132 Unified Function Call Syntax](https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md). + +## `tests/ui/unboxed-closures/` + +`#![feature(unboxed_closures)]`, `Fn`, `FnMut` and `FnOnce` traits + +See [Tracking issue for Fn traits (`unboxed_closures` & `fn_traits` feature)](https://github.com/rust-lang/rust/issues/29625). + +## `tests/ui/underscore-imports/` + +See [Underscore imports | Reference](https://doc.rust-lang.org/reference/items/use-declarations.html#underscore-imports). + +**FIXME**: should become a subdirectory of `tests/ui/imports/`. + +## `tests/ui/underscore-lifetime/`: `'_` elided lifetime + +Exercises [anonymous elided lifetimes](https://doc.rust-lang.org/reference/lifetime-elision.html). + +## `tests/ui/uniform-paths/` + +In uniform paths, if a submodule and an external dependencies have the same name, to depend on the external dependency, one needs to disambiguate it from the submodule using `use ::foo`. Tests revolve around this, for example, check that `self::foo` and `::foo` are not considered ambiguously identical by the compiler. + +Remark: As they are an important Rust 2018 feature, they also get a big subdirectory in `ui/rust-2018/uniform-paths` + +## `tests/ui/uninhabited/`: Uninhabited types + +See [Uninhabited | Reference](https://doc.rust-lang.org/reference/glossary.html?highlight=Uninhabit#uninhabited). + +## `tests/ui/union/` + +See [Unions | Reference](https://doc.rust-lang.org/reference/items/unions.html). + +## `tests/ui/unknown-unstable-lints/`: Attempting to refer to an unstable lint which does not exist + +Tests for trying to use non-existent unstable lints. + +**FIXME**: move this under `tests/ui/lints/`. + +## `tests/ui/unop/`: Unary operators `-`, `*` and `!` + +Tests the three unary operators for negating, dereferencing and inverting, across different contexts. + +## `tests/ui/unpretty/`: `-Z unpretty` command line flag + +The `-Z unpretty` flag outputs various representations of a program's tree in a certain way. + +## `tests/ui/unresolved/` + +Exercises various unresolved errors, ranging from earlier name resolution failures to later method resolution failures. + +## `tests/ui/unsafe/` + +A broad category of tests about unsafe Rust code. + +## `tests/ui/unsafe-binders/`: `#![feature(unsafe_binders)]` + +See [Tracking issue for unsafe binder types #130516](https://github.com/rust-lang/rust/issues/130516). + +## `tests/ui/unsafe-fields/`: `struct`s and `enum`s with an `unsafe` field + +See [Tracking issue for RFC 3458: Unsafe fields #132922](https://github.com/rust-lang/rust/issues/132922). + +## `tests/ui/unsized/`: Zero-sized types, `Sized` trait, object has no known size at compile time + +**FIXME**: between `tests/ui/zero-sized/`, `tests/ui/sized/` and this directory, might need to reorganize them a bit. + +## `tests/ui/unsized-locals/`: `#![feature(unsized_locals, unsized_fn_params)]` + +See: + +- [RFC 1909 Unsized rvalues](https://github.com/rust-lang/rfcs/blob/master/text/1909-unsized-rvalues.md) +- [de-RFC 3829: Remove unsized_locals](https://github.com/rust-lang/rfcs/pull/3829) +- [Tracking issue for RFC #1909: Unsized Rvalues (`unsized_locals`, `unsized_fn_params`)](https://github.com/rust-lang/rust/issues/48055) + +**FIXME**: Seems to also contain more generic tests that fit in `tests/ui/unsized/`. + +## `tests/ui/unused-crate-deps/` + +Exercises the `unused_crate_dependencies` lint. + +## `tests/ui/unwind-abis/` + +**FIXME**: Contains a single test, should likely be rehomed to `tests/ui/abi/`. + +## `tests/ui/use/` + +**FIXME**: merge with `ui/imports`. + +## `tests/ui/variance/`: Covariants, invariants and contravariants + +See [Variance | Reference](https://doc.rust-lang.org/reference/subtyping.html#variance). + +## `tests/ui/variants/`: `enum` variants + +Tests on `enum` variants. + +**FIXME**: Should be rehomed with `tests/ui/enum/`. + +## `tests/ui/version/` + +**FIXME**: Contains a single test described as "Check that rustc accepts various version info flags.", should be rehomed. + +## `tests/ui/warnings/` + +**FIXME**: Contains a single test on non-explicit paths (`::one()`). Should be rehomed probably to `tests/ui/resolve/`. + +## `tests/ui/wasm/` + +These tests target the `wasm32` architecture specifically. They are usually regression tests for WASM-specific bugs which were observed in the past. + +## `tests/ui/wf/`: Well-formedness checking + +Tests on various well-formedness checks, e.g. [Type-checking normal functions](https://rustc-dev-guide.rust-lang.org/traits/lowering-to-logic.html). + +## `tests/ui/where-clauses/` + +Tests on `where` clauses. See [Where clauses | Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses). + +## `tests/ui/while/` + +Tests on the `while` keyword and the `while` construct. + +**FIXME**: merge with `ui/for-loop-while`. + +## `tests/ui/windows-subsystem/`: `#![windows_subsystem = ""]` + +See [the `windows_subsystem` attribute](https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute). + +## `tests/ui/zero-sized/`: Zero-sized types + +See [Zero-Sized Types | Reference](https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts). diff --git a/tests/ui/abi/bad-custom.rs b/tests/ui/abi/bad-custom.rs index e792f0955b91..7c881134ccb4 100644 --- a/tests/ui/abi/bad-custom.rs +++ b/tests/ui/abi/bad-custom.rs @@ -5,7 +5,7 @@ #[unsafe(naked)] extern "custom" fn must_be_unsafe(a: i64) -> i64 { - //~^ ERROR functions with the `"custom"` ABI must be unsafe + //~^ ERROR functions with the "custom" ABI must be unsafe //~| ERROR invalid signature for `extern "custom"` function std::arch::naked_asm!("") } @@ -23,7 +23,7 @@ unsafe extern "custom" fn no_return_type() -> i64 { } unsafe extern "custom" fn double(a: i64) -> i64 { - //~^ ERROR items with the `"custom"` ABI can only be declared externally or defined via naked functions + //~^ ERROR items with the "custom" ABI can only be declared externally or defined via naked functions //~| ERROR invalid signature for `extern "custom"` function unimplemented!() } @@ -32,7 +32,7 @@ struct Thing(i64); impl Thing { unsafe extern "custom" fn is_even(self) -> bool { - //~^ ERROR items with the `"custom"` ABI can only be declared externally or defined via naked functions + //~^ ERROR items with the "custom" ABI can only be declared externally or defined via naked functions //~| ERROR invalid signature for `extern "custom"` function unimplemented!() } @@ -40,7 +40,7 @@ impl Thing { trait BitwiseNot { unsafe extern "custom" fn bitwise_not(a: i64) -> i64 { - //~^ ERROR items with the `"custom"` ABI can only be declared externally or defined via naked functions + //~^ ERROR items with the "custom" ABI can only be declared externally or defined via naked functions //~| ERROR invalid signature for `extern "custom"` function unimplemented!() } @@ -50,14 +50,14 @@ impl BitwiseNot for Thing {} trait Negate { extern "custom" fn negate(a: i64) -> i64; - //~^ ERROR functions with the `"custom"` ABI must be unsafe + //~^ ERROR functions with the "custom" ABI must be unsafe //~| ERROR invalid signature for `extern "custom"` function } impl Negate for Thing { extern "custom" fn negate(a: i64) -> i64 { - //~^ ERROR items with the `"custom"` ABI can only be declared externally or defined via naked functions - //~| ERROR functions with the `"custom"` ABI must be unsafe + //~^ ERROR items with the "custom" ABI can only be declared externally or defined via naked functions + //~| ERROR functions with the "custom" ABI must be unsafe //~| ERROR invalid signature for `extern "custom"` function -a } @@ -68,24 +68,24 @@ unsafe extern "custom" { //~^ ERROR invalid signature for `extern "custom"` function safe fn extern_cannot_be_safe(); - //~^ ERROR foreign functions with the `"custom"` ABI cannot be safe + //~^ ERROR foreign functions with the "custom" ABI cannot be safe } fn caller(f: unsafe extern "custom" fn(i64) -> i64, mut x: i64) -> i64 { unsafe { f(x) } - //~^ ERROR functions with the `"custom"` ABI cannot be called + //~^ ERROR functions with the "custom" ABI cannot be called } fn caller_by_ref(f: &unsafe extern "custom" fn(i64) -> i64, mut x: i64) -> i64 { unsafe { f(x) } - //~^ ERROR functions with the `"custom"` ABI cannot be called + //~^ ERROR functions with the "custom" ABI cannot be called } type Custom = unsafe extern "custom" fn(i64) -> i64; fn caller_alias(f: Custom, mut x: i64) -> i64 { unsafe { f(x) } - //~^ ERROR functions with the `"custom"` ABI cannot be called + //~^ ERROR functions with the "custom" ABI cannot be called } #[unsafe(naked)] @@ -95,8 +95,8 @@ const unsafe extern "custom" fn no_const_fn() { } async unsafe extern "custom" fn no_async_fn() { - //~^ ERROR items with the `"custom"` ABI can only be declared externally or defined via naked functions - //~| ERROR functions with the `"custom"` ABI cannot be `async` + //~^ ERROR items with the "custom" ABI can only be declared externally or defined via naked functions + //~| ERROR functions with the "custom" ABI cannot be `async` } fn no_promotion_to_fn_trait(f: unsafe extern "custom" fn()) -> impl Fn() { @@ -107,15 +107,15 @@ fn no_promotion_to_fn_trait(f: unsafe extern "custom" fn()) -> impl Fn() { pub fn main() { unsafe { assert_eq!(double(21), 42); - //~^ ERROR functions with the `"custom"` ABI cannot be called + //~^ ERROR functions with the "custom" ABI cannot be called assert_eq!(unsafe { increment(41) }, 42); - //~^ ERROR functions with the `"custom"` ABI cannot be called + //~^ ERROR functions with the "custom" ABI cannot be called assert!(Thing(41).is_even()); - //~^ ERROR functions with the `"custom"` ABI cannot be called + //~^ ERROR functions with the "custom" ABI cannot be called assert_eq!(Thing::bitwise_not(42), !42); - //~^ ERROR functions with the `"custom"` ABI cannot be called + //~^ ERROR functions with the "custom" ABI cannot be called } } diff --git a/tests/ui/abi/bad-custom.stderr b/tests/ui/abi/bad-custom.stderr index ec0f11af8980..893382875a22 100644 --- a/tests/ui/abi/bad-custom.stderr +++ b/tests/ui/abi/bad-custom.stderr @@ -1,4 +1,4 @@ -error: functions with the `"custom"` ABI must be unsafe +error: functions with the "custom" ABI must be unsafe --> $DIR/bad-custom.rs:7:1 | LL | extern "custom" fn must_be_unsafe(a: i64) -> i64 { @@ -15,7 +15,7 @@ error: invalid signature for `extern "custom"` function LL | extern "custom" fn must_be_unsafe(a: i64) -> i64 { | ^^^^^^ ^^^ | - = note: functions with the `"custom"` ABI cannot have any parameters or return type + = note: functions with the "custom" ABI cannot have any parameters or return type help: remove the parameters and return type | LL - extern "custom" fn must_be_unsafe(a: i64) -> i64 { @@ -28,7 +28,7 @@ error: invalid signature for `extern "custom"` function LL | unsafe extern "custom" fn no_parameters(a: i64) { | ^^^^^^ | - = note: functions with the `"custom"` ABI cannot have any parameters or return type + = note: functions with the "custom" ABI cannot have any parameters or return type help: remove the parameters and return type | LL - unsafe extern "custom" fn no_parameters(a: i64) { @@ -41,7 +41,7 @@ error: invalid signature for `extern "custom"` function LL | unsafe extern "custom" fn no_return_type() -> i64 { | ^^^ | - = note: functions with the `"custom"` ABI cannot have any parameters or return type + = note: functions with the "custom" ABI cannot have any parameters or return type help: remove the parameters and return type | LL - unsafe extern "custom" fn no_return_type() -> i64 { @@ -54,7 +54,7 @@ error: invalid signature for `extern "custom"` function LL | unsafe extern "custom" fn double(a: i64) -> i64 { | ^^^^^^ ^^^ | - = note: functions with the `"custom"` ABI cannot have any parameters or return type + = note: functions with the "custom" ABI cannot have any parameters or return type help: remove the parameters and return type | LL - unsafe extern "custom" fn double(a: i64) -> i64 { @@ -67,7 +67,7 @@ error: invalid signature for `extern "custom"` function LL | unsafe extern "custom" fn is_even(self) -> bool { | ^^^^ ^^^^ | - = note: functions with the `"custom"` ABI cannot have any parameters or return type + = note: functions with the "custom" ABI cannot have any parameters or return type help: remove the parameters and return type | LL - unsafe extern "custom" fn is_even(self) -> bool { @@ -80,14 +80,14 @@ error: invalid signature for `extern "custom"` function LL | unsafe extern "custom" fn bitwise_not(a: i64) -> i64 { | ^^^^^^ ^^^ | - = note: functions with the `"custom"` ABI cannot have any parameters or return type + = note: functions with the "custom" ABI cannot have any parameters or return type help: remove the parameters and return type | LL - unsafe extern "custom" fn bitwise_not(a: i64) -> i64 { LL + unsafe extern "custom" fn bitwise_not() { | -error: functions with the `"custom"` ABI must be unsafe +error: functions with the "custom" ABI must be unsafe --> $DIR/bad-custom.rs:52:5 | LL | extern "custom" fn negate(a: i64) -> i64; @@ -104,14 +104,14 @@ error: invalid signature for `extern "custom"` function LL | extern "custom" fn negate(a: i64) -> i64; | ^^^^^^ ^^^ | - = note: functions with the `"custom"` ABI cannot have any parameters or return type + = note: functions with the "custom" ABI cannot have any parameters or return type help: remove the parameters and return type | LL - extern "custom" fn negate(a: i64) -> i64; LL + extern "custom" fn negate(); | -error: functions with the `"custom"` ABI must be unsafe +error: functions with the "custom" ABI must be unsafe --> $DIR/bad-custom.rs:58:5 | LL | extern "custom" fn negate(a: i64) -> i64 { @@ -128,7 +128,7 @@ error: invalid signature for `extern "custom"` function LL | extern "custom" fn negate(a: i64) -> i64 { | ^^^^^^ ^^^ | - = note: functions with the `"custom"` ABI cannot have any parameters or return type + = note: functions with the "custom" ABI cannot have any parameters or return type help: remove the parameters and return type | LL - extern "custom" fn negate(a: i64) -> i64 { @@ -141,14 +141,14 @@ error: invalid signature for `extern "custom"` function LL | fn increment(a: i64) -> i64; | ^^^^^^ ^^^ | - = note: functions with the `"custom"` ABI cannot have any parameters or return type + = note: functions with the "custom" ABI cannot have any parameters or return type help: remove the parameters and return type | LL - fn increment(a: i64) -> i64; LL + fn increment(); | -error: foreign functions with the `"custom"` ABI cannot be safe +error: foreign functions with the "custom" ABI cannot be safe --> $DIR/bad-custom.rs:70:5 | LL | safe fn extern_cannot_be_safe(); @@ -160,7 +160,7 @@ LL - safe fn extern_cannot_be_safe(); LL + fn extern_cannot_be_safe(); | -error: functions with the `"custom"` ABI cannot be `async` +error: functions with the "custom" ABI cannot be `async` --> $DIR/bad-custom.rs:97:1 | LL | async unsafe extern "custom" fn no_async_fn() { @@ -172,7 +172,7 @@ LL - async unsafe extern "custom" fn no_async_fn() { LL + unsafe extern "custom" fn no_async_fn() { | -error: items with the `"custom"` ABI can only be declared externally or defined via naked functions +error: items with the "custom" ABI can only be declared externally or defined via naked functions --> $DIR/bad-custom.rs:97:1 | LL | async unsafe extern "custom" fn no_async_fn() { @@ -197,7 +197,7 @@ LL | f = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe extern "custom" fn()` in a closure with no arguments: `|| { /* code */ }` -error: items with the `"custom"` ABI can only be declared externally or defined via naked functions +error: items with the "custom" ABI can only be declared externally or defined via naked functions --> $DIR/bad-custom.rs:25:1 | LL | unsafe extern "custom" fn double(a: i64) -> i64 { @@ -209,7 +209,7 @@ LL + #[unsafe(naked)] LL | unsafe extern "custom" fn double(a: i64) -> i64 { | -error: items with the `"custom"` ABI can only be declared externally or defined via naked functions +error: items with the "custom" ABI can only be declared externally or defined via naked functions --> $DIR/bad-custom.rs:34:5 | LL | unsafe extern "custom" fn is_even(self) -> bool { @@ -221,7 +221,7 @@ LL + #[unsafe(naked)] LL | unsafe extern "custom" fn is_even(self) -> bool { | -error: items with the `"custom"` ABI can only be declared externally or defined via naked functions +error: items with the "custom" ABI can only be declared externally or defined via naked functions --> $DIR/bad-custom.rs:42:5 | LL | unsafe extern "custom" fn bitwise_not(a: i64) -> i64 { @@ -233,7 +233,7 @@ LL + #[unsafe(naked)] LL | unsafe extern "custom" fn bitwise_not(a: i64) -> i64 { | -error: items with the `"custom"` ABI can only be declared externally or defined via naked functions +error: items with the "custom" ABI can only be declared externally or defined via naked functions --> $DIR/bad-custom.rs:58:5 | LL | extern "custom" fn negate(a: i64) -> i64 { @@ -245,43 +245,85 @@ LL + #[unsafe(naked)] LL | extern "custom" fn negate(a: i64) -> i64 { | -error: functions with the `"custom"` ABI cannot be called +error: functions with the "custom" ABI cannot be called + --> $DIR/bad-custom.rs:75:14 + | +LL | unsafe { f(x) } + | ^^^^ + | +note: an `extern "custom"` function can only be called using inline assembly --> $DIR/bad-custom.rs:75:14 | LL | unsafe { f(x) } | ^^^^ -error: functions with the `"custom"` ABI cannot be called +error: functions with the "custom" ABI cannot be called + --> $DIR/bad-custom.rs:80:14 + | +LL | unsafe { f(x) } + | ^^^^ + | +note: an `extern "custom"` function can only be called using inline assembly --> $DIR/bad-custom.rs:80:14 | LL | unsafe { f(x) } | ^^^^ -error: functions with the `"custom"` ABI cannot be called +error: functions with the "custom" ABI cannot be called + --> $DIR/bad-custom.rs:87:14 + | +LL | unsafe { f(x) } + | ^^^^ + | +note: an `extern "custom"` function can only be called using inline assembly --> $DIR/bad-custom.rs:87:14 | LL | unsafe { f(x) } | ^^^^ -error: functions with the `"custom"` ABI cannot be called +error: functions with the "custom" ABI cannot be called + --> $DIR/bad-custom.rs:109:20 + | +LL | assert_eq!(double(21), 42); + | ^^^^^^^^^^ + | +note: an `extern "custom"` function can only be called using inline assembly --> $DIR/bad-custom.rs:109:20 | LL | assert_eq!(double(21), 42); | ^^^^^^^^^^ -error: functions with the `"custom"` ABI cannot be called +error: functions with the "custom" ABI cannot be called + --> $DIR/bad-custom.rs:112:29 + | +LL | assert_eq!(unsafe { increment(41) }, 42); + | ^^^^^^^^^^^^^ + | +note: an `extern "custom"` function can only be called using inline assembly --> $DIR/bad-custom.rs:112:29 | LL | assert_eq!(unsafe { increment(41) }, 42); | ^^^^^^^^^^^^^ -error: functions with the `"custom"` ABI cannot be called +error: functions with the "custom" ABI cannot be called + --> $DIR/bad-custom.rs:115:17 + | +LL | assert!(Thing(41).is_even()); + | ^^^^^^^^^^^^^^^^^^^ + | +note: an `extern "custom"` function can only be called using inline assembly --> $DIR/bad-custom.rs:115:17 | LL | assert!(Thing(41).is_even()); | ^^^^^^^^^^^^^^^^^^^ -error: functions with the `"custom"` ABI cannot be called +error: functions with the "custom" ABI cannot be called + --> $DIR/bad-custom.rs:118:20 + | +LL | assert_eq!(Thing::bitwise_not(42), !42); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: an `extern "custom"` function can only be called using inline assembly --> $DIR/bad-custom.rs:118:20 | LL | assert_eq!(Thing::bitwise_not(42), !42); diff --git a/tests/ui/abi/cannot-be-called.avr.stderr b/tests/ui/abi/cannot-be-called.avr.stderr new file mode 100644 index 000000000000..1129893cbfaf --- /dev/null +++ b/tests/ui/abi/cannot-be-called.avr.stderr @@ -0,0 +1,75 @@ +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:37:8 + | +LL | extern "msp430-interrupt" fn msp430() {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:41:8 + | +LL | extern "riscv-interrupt-m" fn riscv_m() {} + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:43:8 + | +LL | extern "riscv-interrupt-s" fn riscv_s() {} + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "x86-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:45:8 + | +LL | extern "x86-interrupt" fn x86() {} + | ^^^^^^^^^^^^^^^ + +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:70:25 + | +LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:76:26 + | +LL | fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:82:26 + | +LL | fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "x86-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:88:22 + | +LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { + | ^^^^^^^^^^^^^^^ + +error: functions with the "avr-interrupt" ABI cannot be called + --> $DIR/cannot-be-called.rs:50:5 + | +LL | avr(); + | ^^^^^ + | +note: an `extern "avr-interrupt"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:50:5 + | +LL | avr(); + | ^^^^^ + +error: functions with the "avr-interrupt" ABI cannot be called + --> $DIR/cannot-be-called.rs:66:5 + | +LL | f() + | ^^^ + | +note: an `extern "avr-interrupt"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:66:5 + | +LL | f() + | ^^^ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/cannot-be-called.i686.stderr b/tests/ui/abi/cannot-be-called.i686.stderr new file mode 100644 index 000000000000..024d5e2e93d6 --- /dev/null +++ b/tests/ui/abi/cannot-be-called.i686.stderr @@ -0,0 +1,75 @@ +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:37:8 + | +LL | extern "msp430-interrupt" fn msp430() {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:39:8 + | +LL | extern "avr-interrupt" fn avr() {} + | ^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:41:8 + | +LL | extern "riscv-interrupt-m" fn riscv_m() {} + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:43:8 + | +LL | extern "riscv-interrupt-s" fn riscv_s() {} + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:64:22 + | +LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { + | ^^^^^^^^^^^^^^^ + +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:70:25 + | +LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:76:26 + | +LL | fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:82:26 + | +LL | fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + +error: functions with the "x86-interrupt" ABI cannot be called + --> $DIR/cannot-be-called.rs:58:5 + | +LL | x86(); + | ^^^^^ + | +note: an `extern "x86-interrupt"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:58:5 + | +LL | x86(); + | ^^^^^ + +error: functions with the "x86-interrupt" ABI cannot be called + --> $DIR/cannot-be-called.rs:90:5 + | +LL | f() + | ^^^ + | +note: an `extern "x86-interrupt"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:90:5 + | +LL | f() + | ^^^ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/cannot-be-called.msp430.stderr b/tests/ui/abi/cannot-be-called.msp430.stderr new file mode 100644 index 000000000000..52d7d792510e --- /dev/null +++ b/tests/ui/abi/cannot-be-called.msp430.stderr @@ -0,0 +1,75 @@ +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:39:8 + | +LL | extern "avr-interrupt" fn avr() {} + | ^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:41:8 + | +LL | extern "riscv-interrupt-m" fn riscv_m() {} + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:43:8 + | +LL | extern "riscv-interrupt-s" fn riscv_s() {} + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "x86-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:45:8 + | +LL | extern "x86-interrupt" fn x86() {} + | ^^^^^^^^^^^^^^^ + +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:64:22 + | +LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { + | ^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:76:26 + | +LL | fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:82:26 + | +LL | fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "x86-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:88:22 + | +LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { + | ^^^^^^^^^^^^^^^ + +error: functions with the "msp430-interrupt" ABI cannot be called + --> $DIR/cannot-be-called.rs:52:5 + | +LL | msp430(); + | ^^^^^^^^ + | +note: an `extern "msp430-interrupt"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:52:5 + | +LL | msp430(); + | ^^^^^^^^ + +error: functions with the "msp430-interrupt" ABI cannot be called + --> $DIR/cannot-be-called.rs:72:5 + | +LL | f() + | ^^^ + | +note: an `extern "msp430-interrupt"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:72:5 + | +LL | f() + | ^^^ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/cannot-be-called.riscv32.stderr b/tests/ui/abi/cannot-be-called.riscv32.stderr new file mode 100644 index 000000000000..119d93bd58e9 --- /dev/null +++ b/tests/ui/abi/cannot-be-called.riscv32.stderr @@ -0,0 +1,87 @@ +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:37:8 + | +LL | extern "msp430-interrupt" fn msp430() {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:39:8 + | +LL | extern "avr-interrupt" fn avr() {} + | ^^^^^^^^^^^^^^^ + +error[E0570]: "x86-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:45:8 + | +LL | extern "x86-interrupt" fn x86() {} + | ^^^^^^^^^^^^^^^ + +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:64:22 + | +LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { + | ^^^^^^^^^^^^^^^ + +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:70:25 + | +LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^ + +error[E0570]: "x86-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:88:22 + | +LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { + | ^^^^^^^^^^^^^^^ + +error: functions with the "riscv-interrupt-m" ABI cannot be called + --> $DIR/cannot-be-called.rs:54:5 + | +LL | riscv_m(); + | ^^^^^^^^^ + | +note: an `extern "riscv-interrupt-m"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:54:5 + | +LL | riscv_m(); + | ^^^^^^^^^ + +error: functions with the "riscv-interrupt-s" ABI cannot be called + --> $DIR/cannot-be-called.rs:56:5 + | +LL | riscv_s(); + | ^^^^^^^^^ + | +note: an `extern "riscv-interrupt-s"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:56:5 + | +LL | riscv_s(); + | ^^^^^^^^^ + +error: functions with the "riscv-interrupt-m" ABI cannot be called + --> $DIR/cannot-be-called.rs:78:5 + | +LL | f() + | ^^^ + | +note: an `extern "riscv-interrupt-m"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:78:5 + | +LL | f() + | ^^^ + +error: functions with the "riscv-interrupt-s" ABI cannot be called + --> $DIR/cannot-be-called.rs:84:5 + | +LL | f() + | ^^^ + | +note: an `extern "riscv-interrupt-s"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:84:5 + | +LL | f() + | ^^^ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/cannot-be-called.riscv64.stderr b/tests/ui/abi/cannot-be-called.riscv64.stderr new file mode 100644 index 000000000000..119d93bd58e9 --- /dev/null +++ b/tests/ui/abi/cannot-be-called.riscv64.stderr @@ -0,0 +1,87 @@ +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:37:8 + | +LL | extern "msp430-interrupt" fn msp430() {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:39:8 + | +LL | extern "avr-interrupt" fn avr() {} + | ^^^^^^^^^^^^^^^ + +error[E0570]: "x86-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:45:8 + | +LL | extern "x86-interrupt" fn x86() {} + | ^^^^^^^^^^^^^^^ + +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:64:22 + | +LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { + | ^^^^^^^^^^^^^^^ + +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:70:25 + | +LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^ + +error[E0570]: "x86-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:88:22 + | +LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { + | ^^^^^^^^^^^^^^^ + +error: functions with the "riscv-interrupt-m" ABI cannot be called + --> $DIR/cannot-be-called.rs:54:5 + | +LL | riscv_m(); + | ^^^^^^^^^ + | +note: an `extern "riscv-interrupt-m"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:54:5 + | +LL | riscv_m(); + | ^^^^^^^^^ + +error: functions with the "riscv-interrupt-s" ABI cannot be called + --> $DIR/cannot-be-called.rs:56:5 + | +LL | riscv_s(); + | ^^^^^^^^^ + | +note: an `extern "riscv-interrupt-s"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:56:5 + | +LL | riscv_s(); + | ^^^^^^^^^ + +error: functions with the "riscv-interrupt-m" ABI cannot be called + --> $DIR/cannot-be-called.rs:78:5 + | +LL | f() + | ^^^ + | +note: an `extern "riscv-interrupt-m"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:78:5 + | +LL | f() + | ^^^ + +error: functions with the "riscv-interrupt-s" ABI cannot be called + --> $DIR/cannot-be-called.rs:84:5 + | +LL | f() + | ^^^ + | +note: an `extern "riscv-interrupt-s"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:84:5 + | +LL | f() + | ^^^ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/cannot-be-called.rs b/tests/ui/abi/cannot-be-called.rs new file mode 100644 index 000000000000..af979d65d334 --- /dev/null +++ b/tests/ui/abi/cannot-be-called.rs @@ -0,0 +1,92 @@ +/*! Tests entry-point ABIs cannot be called + +Interrupt ABIs share similar semantics, in that they are special entry-points unusable by Rust. +So we test that they error in essentially all of the same places. +*/ +//@ add-core-stubs +//@ revisions: x64 x64_win i686 riscv32 riscv64 avr msp430 +// +//@ [x64] needs-llvm-components: x86 +//@ [x64] compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib +//@ [x64_win] needs-llvm-components: x86 +//@ [x64_win] compile-flags: --target=x86_64-pc-windows-msvc --crate-type=rlib +//@ [i686] needs-llvm-components: x86 +//@ [i686] compile-flags: --target=i686-unknown-linux-gnu --crate-type=rlib +//@ [riscv32] needs-llvm-components: riscv +//@ [riscv32] compile-flags: --target=riscv32i-unknown-none-elf --crate-type=rlib +//@ [riscv64] needs-llvm-components: riscv +//@ [riscv64] compile-flags: --target=riscv64gc-unknown-none-elf --crate-type=rlib +//@ [avr] needs-llvm-components: avr +//@ [avr] compile-flags: --target=avr-none -C target-cpu=atmega328p --crate-type=rlib +//@ [msp430] needs-llvm-components: msp430 +//@ [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib +#![no_core] +#![feature( + no_core, + abi_msp430_interrupt, + abi_avr_interrupt, + abi_x86_interrupt, + abi_riscv_interrupt +)] + +extern crate minicore; +use minicore::*; + +/* extern "interrupt" definition */ + +extern "msp430-interrupt" fn msp430() {} +//[x64,x64_win,i686,riscv32,riscv64,avr]~^ ERROR is not a supported ABI +extern "avr-interrupt" fn avr() {} +//[x64,x64_win,i686,riscv32,riscv64,msp430]~^ ERROR is not a supported ABI +extern "riscv-interrupt-m" fn riscv_m() {} +//[x64,x64_win,i686,avr,msp430]~^ ERROR is not a supported ABI +extern "riscv-interrupt-s" fn riscv_s() {} +//[x64,x64_win,i686,avr,msp430]~^ ERROR is not a supported ABI +extern "x86-interrupt" fn x86() {} +//[riscv32,riscv64,avr,msp430]~^ ERROR is not a supported ABI + +/* extern "interrupt" calls */ +fn call_the_interrupts() { + avr(); + //[avr]~^ ERROR functions with the "avr-interrupt" ABI cannot be called + msp430(); + //[msp430]~^ ERROR functions with the "msp430-interrupt" ABI cannot be called + riscv_m(); + //[riscv32,riscv64]~^ ERROR functions with the "riscv-interrupt-m" ABI cannot be called + riscv_s(); + //[riscv32,riscv64]~^ ERROR functions with the "riscv-interrupt-s" ABI cannot be called + x86(); + //[x64,x64_win,i686]~^ ERROR functions with the "x86-interrupt" ABI cannot be called +} + +/* extern "interrupt" fnptr calls */ + +fn avr_ptr(f: extern "avr-interrupt" fn()) { + //[x64,x64_win,i686,riscv32,riscv64,msp430]~^ ERROR is not a supported ABI + f() + //[avr]~^ ERROR functions with the "avr-interrupt" ABI cannot be called +} + +fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + //[x64,x64_win,i686,riscv32,riscv64,avr]~^ ERROR is not a supported ABI + f() + //[msp430]~^ ERROR functions with the "msp430-interrupt" ABI cannot be called +} + +fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) { + //[x64,x64_win,i686,avr,msp430]~^ ERROR is not a supported ABI + f() + //[riscv32,riscv64]~^ ERROR functions with the "riscv-interrupt-m" ABI cannot be called +} + +fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) { + //[x64,x64_win,i686,avr,msp430]~^ ERROR is not a supported ABI + f() + //[riscv32,riscv64]~^ ERROR functions with the "riscv-interrupt-s" ABI cannot be called +} + +fn x86_ptr(f: extern "x86-interrupt" fn()) { + //[riscv32,riscv64,avr,msp430]~^ ERROR is not a supported ABI + f() + //[x64,x64_win,i686]~^ ERROR functions with the "x86-interrupt" ABI cannot be called +} diff --git a/tests/ui/abi/cannot-be-called.x64.stderr b/tests/ui/abi/cannot-be-called.x64.stderr new file mode 100644 index 000000000000..024d5e2e93d6 --- /dev/null +++ b/tests/ui/abi/cannot-be-called.x64.stderr @@ -0,0 +1,75 @@ +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:37:8 + | +LL | extern "msp430-interrupt" fn msp430() {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:39:8 + | +LL | extern "avr-interrupt" fn avr() {} + | ^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:41:8 + | +LL | extern "riscv-interrupt-m" fn riscv_m() {} + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:43:8 + | +LL | extern "riscv-interrupt-s" fn riscv_s() {} + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:64:22 + | +LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { + | ^^^^^^^^^^^^^^^ + +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:70:25 + | +LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:76:26 + | +LL | fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:82:26 + | +LL | fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + +error: functions with the "x86-interrupt" ABI cannot be called + --> $DIR/cannot-be-called.rs:58:5 + | +LL | x86(); + | ^^^^^ + | +note: an `extern "x86-interrupt"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:58:5 + | +LL | x86(); + | ^^^^^ + +error: functions with the "x86-interrupt" ABI cannot be called + --> $DIR/cannot-be-called.rs:90:5 + | +LL | f() + | ^^^ + | +note: an `extern "x86-interrupt"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:90:5 + | +LL | f() + | ^^^ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/cannot-be-called.x64_win.stderr b/tests/ui/abi/cannot-be-called.x64_win.stderr new file mode 100644 index 000000000000..024d5e2e93d6 --- /dev/null +++ b/tests/ui/abi/cannot-be-called.x64_win.stderr @@ -0,0 +1,75 @@ +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:37:8 + | +LL | extern "msp430-interrupt" fn msp430() {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:39:8 + | +LL | extern "avr-interrupt" fn avr() {} + | ^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:41:8 + | +LL | extern "riscv-interrupt-m" fn riscv_m() {} + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:43:8 + | +LL | extern "riscv-interrupt-s" fn riscv_s() {} + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:64:22 + | +LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { + | ^^^^^^^^^^^^^^^ + +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:70:25 + | +LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { + | ^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:76:26 + | +LL | fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target + --> $DIR/cannot-be-called.rs:82:26 + | +LL | fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) { + | ^^^^^^^^^^^^^^^^^^^ + +error: functions with the "x86-interrupt" ABI cannot be called + --> $DIR/cannot-be-called.rs:58:5 + | +LL | x86(); + | ^^^^^ + | +note: an `extern "x86-interrupt"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:58:5 + | +LL | x86(); + | ^^^^^ + +error: functions with the "x86-interrupt" ABI cannot be called + --> $DIR/cannot-be-called.rs:90:5 + | +LL | f() + | ^^^ + | +note: an `extern "x86-interrupt"` function can only be called using inline assembly + --> $DIR/cannot-be-called.rs:90:5 + | +LL | f() + | ^^^ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/cannot-be-coroutine.avr.stderr b/tests/ui/abi/cannot-be-coroutine.avr.stderr new file mode 100644 index 000000000000..b06da0f3352e --- /dev/null +++ b/tests/ui/abi/cannot-be-coroutine.avr.stderr @@ -0,0 +1,23 @@ +error: functions with the "avr-interrupt" ABI cannot be `async` + --> $DIR/cannot-be-coroutine.rs:36:1 + | +LL | async extern "avr-interrupt" fn avr() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `async` keyword from this definiton + | +LL - async extern "avr-interrupt" fn avr() { +LL + extern "avr-interrupt" fn avr() { + | + +error: requires `ResumeTy` lang_item + --> $DIR/cannot-be-coroutine.rs:32:19 + | +LL | async fn vanilla(){ + | ___________________^ +LL | | +LL | | } + | |_^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/abi/cannot-be-coroutine.i686.stderr b/tests/ui/abi/cannot-be-coroutine.i686.stderr new file mode 100644 index 000000000000..cbbddd087c8a --- /dev/null +++ b/tests/ui/abi/cannot-be-coroutine.i686.stderr @@ -0,0 +1,23 @@ +error: functions with the "x86-interrupt" ABI cannot be `async` + --> $DIR/cannot-be-coroutine.rs:52:1 + | +LL | async extern "x86-interrupt" fn x86() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `async` keyword from this definiton + | +LL - async extern "x86-interrupt" fn x86() { +LL + extern "x86-interrupt" fn x86() { + | + +error: requires `ResumeTy` lang_item + --> $DIR/cannot-be-coroutine.rs:32:19 + | +LL | async fn vanilla(){ + | ___________________^ +LL | | +LL | | } + | |_^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/abi/cannot-be-coroutine.msp430.stderr b/tests/ui/abi/cannot-be-coroutine.msp430.stderr new file mode 100644 index 000000000000..951ce13b6055 --- /dev/null +++ b/tests/ui/abi/cannot-be-coroutine.msp430.stderr @@ -0,0 +1,23 @@ +error: functions with the "msp430-interrupt" ABI cannot be `async` + --> $DIR/cannot-be-coroutine.rs:40:1 + | +LL | async extern "msp430-interrupt" fn msp430() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `async` keyword from this definiton + | +LL - async extern "msp430-interrupt" fn msp430() { +LL + extern "msp430-interrupt" fn msp430() { + | + +error: requires `ResumeTy` lang_item + --> $DIR/cannot-be-coroutine.rs:32:19 + | +LL | async fn vanilla(){ + | ___________________^ +LL | | +LL | | } + | |_^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/abi/cannot-be-coroutine.riscv32.stderr b/tests/ui/abi/cannot-be-coroutine.riscv32.stderr new file mode 100644 index 000000000000..8e3b3a2940a1 --- /dev/null +++ b/tests/ui/abi/cannot-be-coroutine.riscv32.stderr @@ -0,0 +1,35 @@ +error: functions with the "riscv-interrupt-m" ABI cannot be `async` + --> $DIR/cannot-be-coroutine.rs:44:1 + | +LL | async extern "riscv-interrupt-m" fn riscv_m() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `async` keyword from this definiton + | +LL - async extern "riscv-interrupt-m" fn riscv_m() { +LL + extern "riscv-interrupt-m" fn riscv_m() { + | + +error: functions with the "riscv-interrupt-s" ABI cannot be `async` + --> $DIR/cannot-be-coroutine.rs:48:1 + | +LL | async extern "riscv-interrupt-s" fn riscv_s() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `async` keyword from this definiton + | +LL - async extern "riscv-interrupt-s" fn riscv_s() { +LL + extern "riscv-interrupt-s" fn riscv_s() { + | + +error: requires `ResumeTy` lang_item + --> $DIR/cannot-be-coroutine.rs:32:19 + | +LL | async fn vanilla(){ + | ___________________^ +LL | | +LL | | } + | |_^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/abi/cannot-be-coroutine.riscv64.stderr b/tests/ui/abi/cannot-be-coroutine.riscv64.stderr new file mode 100644 index 000000000000..8e3b3a2940a1 --- /dev/null +++ b/tests/ui/abi/cannot-be-coroutine.riscv64.stderr @@ -0,0 +1,35 @@ +error: functions with the "riscv-interrupt-m" ABI cannot be `async` + --> $DIR/cannot-be-coroutine.rs:44:1 + | +LL | async extern "riscv-interrupt-m" fn riscv_m() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `async` keyword from this definiton + | +LL - async extern "riscv-interrupt-m" fn riscv_m() { +LL + extern "riscv-interrupt-m" fn riscv_m() { + | + +error: functions with the "riscv-interrupt-s" ABI cannot be `async` + --> $DIR/cannot-be-coroutine.rs:48:1 + | +LL | async extern "riscv-interrupt-s" fn riscv_s() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `async` keyword from this definiton + | +LL - async extern "riscv-interrupt-s" fn riscv_s() { +LL + extern "riscv-interrupt-s" fn riscv_s() { + | + +error: requires `ResumeTy` lang_item + --> $DIR/cannot-be-coroutine.rs:32:19 + | +LL | async fn vanilla(){ + | ___________________^ +LL | | +LL | | } + | |_^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/abi/cannot-be-coroutine.rs b/tests/ui/abi/cannot-be-coroutine.rs new file mode 100644 index 000000000000..7270a55f69ec --- /dev/null +++ b/tests/ui/abi/cannot-be-coroutine.rs @@ -0,0 +1,54 @@ +//@ add-core-stubs +//@ edition: 2021 +//@ revisions: x64 x64_win i686 riscv32 riscv64 avr msp430 +// +//@ [x64] needs-llvm-components: x86 +//@ [x64] compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib +//@ [x64_win] needs-llvm-components: x86 +//@ [x64_win] compile-flags: --target=x86_64-pc-windows-msvc --crate-type=rlib +//@ [i686] needs-llvm-components: x86 +//@ [i686] compile-flags: --target=i686-unknown-linux-gnu --crate-type=rlib +//@ [riscv32] needs-llvm-components: riscv +//@ [riscv32] compile-flags: --target=riscv32i-unknown-none-elf --crate-type=rlib +//@ [riscv64] needs-llvm-components: riscv +//@ [riscv64] compile-flags: --target=riscv64gc-unknown-none-elf --crate-type=rlib +//@ [avr] needs-llvm-components: avr +//@ [avr] compile-flags: --target=avr-none -C target-cpu=atmega328p --crate-type=rlib +//@ [msp430] needs-llvm-components: msp430 +//@ [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib +#![no_core] +#![feature( + no_core, + abi_msp430_interrupt, + abi_avr_interrupt, + abi_x86_interrupt, + abi_riscv_interrupt +)] + +extern crate minicore; +use minicore::*; + +// We ignore this error; implementing all of the async-related lang items is not worth it. +async fn vanilla(){ + //~^ ERROR requires `ResumeTy` lang_item +} + +async extern "avr-interrupt" fn avr() { + //[avr]~^ ERROR functions with the "avr-interrupt" ABI cannot be `async` +} + +async extern "msp430-interrupt" fn msp430() { + //[msp430]~^ ERROR functions with the "msp430-interrupt" ABI cannot be `async` +} + +async extern "riscv-interrupt-m" fn riscv_m() { + //[riscv32,riscv64]~^ ERROR functions with the "riscv-interrupt-m" ABI cannot be `async` +} + +async extern "riscv-interrupt-s" fn riscv_s() { + //[riscv32,riscv64]~^ ERROR functions with the "riscv-interrupt-s" ABI cannot be `async` +} + +async extern "x86-interrupt" fn x86() { + //[x64,x64_win,i686]~^ ERROR functions with the "x86-interrupt" ABI cannot be `async` +} diff --git a/tests/ui/abi/cannot-be-coroutine.x64.stderr b/tests/ui/abi/cannot-be-coroutine.x64.stderr new file mode 100644 index 000000000000..cbbddd087c8a --- /dev/null +++ b/tests/ui/abi/cannot-be-coroutine.x64.stderr @@ -0,0 +1,23 @@ +error: functions with the "x86-interrupt" ABI cannot be `async` + --> $DIR/cannot-be-coroutine.rs:52:1 + | +LL | async extern "x86-interrupt" fn x86() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `async` keyword from this definiton + | +LL - async extern "x86-interrupt" fn x86() { +LL + extern "x86-interrupt" fn x86() { + | + +error: requires `ResumeTy` lang_item + --> $DIR/cannot-be-coroutine.rs:32:19 + | +LL | async fn vanilla(){ + | ___________________^ +LL | | +LL | | } + | |_^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/abi/cannot-be-coroutine.x64_win.stderr b/tests/ui/abi/cannot-be-coroutine.x64_win.stderr new file mode 100644 index 000000000000..cbbddd087c8a --- /dev/null +++ b/tests/ui/abi/cannot-be-coroutine.x64_win.stderr @@ -0,0 +1,23 @@ +error: functions with the "x86-interrupt" ABI cannot be `async` + --> $DIR/cannot-be-coroutine.rs:52:1 + | +LL | async extern "x86-interrupt" fn x86() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `async` keyword from this definiton + | +LL - async extern "x86-interrupt" fn x86() { +LL + extern "x86-interrupt" fn x86() { + | + +error: requires `ResumeTy` lang_item + --> $DIR/cannot-be-coroutine.rs:32:19 + | +LL | async fn vanilla(){ + | ___________________^ +LL | | +LL | | } + | |_^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/abi/invalid-call-abi-ctfe.rs b/tests/ui/abi/invalid-call-abi-ctfe.rs new file mode 100644 index 000000000000..343cc728fe3b --- /dev/null +++ b/tests/ui/abi/invalid-call-abi-ctfe.rs @@ -0,0 +1,14 @@ +// Fix for #142969 where an invalid ABI in a signature still had its call ABI computed +// because CTFE tried to evaluate it, despite previous errors during AST-to-HIR lowering. + +#![feature(rustc_attrs)] + +const extern "rust-invalid" fn foo() { + //~^ ERROR "rust-invalid" is not a supported ABI for the current target + panic!() +} + +const _: () = foo(); + + +fn main() {} diff --git a/tests/ui/abi/invalid-call-abi-ctfe.stderr b/tests/ui/abi/invalid-call-abi-ctfe.stderr new file mode 100644 index 000000000000..402de4b69b97 --- /dev/null +++ b/tests/ui/abi/invalid-call-abi-ctfe.stderr @@ -0,0 +1,9 @@ +error[E0570]: "rust-invalid" is not a supported ABI for the current target + --> $DIR/invalid-call-abi-ctfe.rs:6:14 + | +LL | const extern "rust-invalid" fn foo() { + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/invalid-call-abi.rs b/tests/ui/abi/invalid-call-abi.rs new file mode 100644 index 000000000000..076ddd91ab0f --- /dev/null +++ b/tests/ui/abi/invalid-call-abi.rs @@ -0,0 +1,12 @@ +// Tests the `"rustc-invalid"` ABI, which is never canonizable. + +#![feature(rustc_attrs)] + +const extern "rust-invalid" fn foo() { + //~^ ERROR "rust-invalid" is not a supported ABI for the current target + panic!() +} + +fn main() { + foo(); +} diff --git a/tests/ui/abi/invalid-call-abi.stderr b/tests/ui/abi/invalid-call-abi.stderr new file mode 100644 index 000000000000..c4a90158dcfe --- /dev/null +++ b/tests/ui/abi/invalid-call-abi.stderr @@ -0,0 +1,9 @@ +error[E0570]: "rust-invalid" is not a supported ABI for the current target + --> $DIR/invalid-call-abi.rs:5:14 + | +LL | const extern "rust-invalid" fn foo() { + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported-abi-transmute.rs b/tests/ui/abi/unsupported-abi-transmute.rs new file mode 100644 index 000000000000..42aa180e1fd8 --- /dev/null +++ b/tests/ui/abi/unsupported-abi-transmute.rs @@ -0,0 +1,12 @@ +// Check we error before unsupported ABIs reach codegen stages. + +//@ edition: 2018 +//@ compile-flags: --crate-type=lib +#![feature(rustc_attrs)] + +use core::mem; + +fn anything() { + let a = unsafe { mem::transmute::(4) }(2); + //~^ ERROR: is not a supported ABI for the current target [E0570] +} diff --git a/tests/ui/abi/unsupported-abi-transmute.stderr b/tests/ui/abi/unsupported-abi-transmute.stderr new file mode 100644 index 000000000000..f1d202b1a1c7 --- /dev/null +++ b/tests/ui/abi/unsupported-abi-transmute.stderr @@ -0,0 +1,9 @@ +error[E0570]: "rust-invalid" is not a supported ABI for the current target + --> $DIR/unsupported-abi-transmute.rs:10:53 + | +LL | let a = unsafe { mem::transmute::(4) }(2); + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported-in-impls.rs b/tests/ui/abi/unsupported-in-impls.rs new file mode 100644 index 000000000000..71797954865a --- /dev/null +++ b/tests/ui/abi/unsupported-in-impls.rs @@ -0,0 +1,36 @@ +// Test for https://github.com/rust-lang/rust/issues/86232 +// Due to AST-to-HIR lowering nuances, we used to allow unsupported ABIs to "leak" into the HIR +// without being checked, as we would check after generating the ExternAbi. +// Checking afterwards only works if we examine every HIR construct that contains an ExternAbi, +// and those may be very different in HIR, even if they read the same in source. +// This made it very easy to make mistakes. +// +// Here we test that an unsupported ABI in various impl-related positions will be rejected, +// both in the original declarations and the actual implementations. + +#![feature(rustc_attrs)] +//@ compile-flags: --crate-type lib + +pub struct FnPtrBearer { + pub ptr: extern "rust-invalid" fn(), + //~^ ERROR: is not a supported ABI +} + +impl FnPtrBearer { + pub extern "rust-invalid" fn inherent_fn(self) { + //~^ ERROR: is not a supported ABI + (self.ptr)() + } +} + +pub trait Trait { + extern "rust-invalid" fn trait_fn(self); + //~^ ERROR: is not a supported ABI +} + +impl Trait for FnPtrBearer { + extern "rust-invalid" fn trait_fn(self) { + //~^ ERROR: is not a supported ABI + self.inherent_fn() + } +} diff --git a/tests/ui/abi/unsupported-in-impls.stderr b/tests/ui/abi/unsupported-in-impls.stderr new file mode 100644 index 000000000000..d7a188f8a040 --- /dev/null +++ b/tests/ui/abi/unsupported-in-impls.stderr @@ -0,0 +1,27 @@ +error[E0570]: "rust-invalid" is not a supported ABI for the current target + --> $DIR/unsupported-in-impls.rs:15:21 + | +LL | pub ptr: extern "rust-invalid" fn(), + | ^^^^^^^^^^^^^^ + +error[E0570]: "rust-invalid" is not a supported ABI for the current target + --> $DIR/unsupported-in-impls.rs:20:16 + | +LL | pub extern "rust-invalid" fn inherent_fn(self) { + | ^^^^^^^^^^^^^^ + +error[E0570]: "rust-invalid" is not a supported ABI for the current target + --> $DIR/unsupported-in-impls.rs:27:12 + | +LL | extern "rust-invalid" fn trait_fn(self); + | ^^^^^^^^^^^^^^ + +error[E0570]: "rust-invalid" is not a supported ABI for the current target + --> $DIR/unsupported-in-impls.rs:32:12 + | +LL | extern "rust-invalid" fn trait_fn(self) { + | ^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported-varargs-fnptr.rs b/tests/ui/abi/unsupported-varargs-fnptr.rs new file mode 100644 index 000000000000..1d23916d0390 --- /dev/null +++ b/tests/ui/abi/unsupported-varargs-fnptr.rs @@ -0,0 +1,19 @@ +// FIXME(workingjubilee): add revisions and generalize to other platform-specific varargs ABIs, +// preferably after the only-arch directive is enhanced with an "or pattern" syntax +// NOTE: This deliberately tests an ABI that supports varargs, so no `extern "rust-invalid"` +//@ only-x86_64 + +// We have to use this flag to force ABI computation of an invalid ABI +//@ compile-flags: -Clink-dead-code + +#![feature(extended_varargs_abi_support)] + +// sometimes fn ptrs with varargs make layout and ABI computation ICE +// as found in https://github.com/rust-lang/rust/issues/142107 + +fn aapcs(f: extern "aapcs" fn(usize, ...)) { +//~^ ERROR [E0570] +// Note we DO NOT have to actually make a call to trigger the ICE! +} + +fn main() {} diff --git a/tests/ui/abi/unsupported-varargs-fnptr.stderr b/tests/ui/abi/unsupported-varargs-fnptr.stderr new file mode 100644 index 000000000000..238f2b313304 --- /dev/null +++ b/tests/ui/abi/unsupported-varargs-fnptr.stderr @@ -0,0 +1,9 @@ +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported-varargs-fnptr.rs:14:20 + | +LL | fn aapcs(f: extern "aapcs" fn(usize, ...)) { + | ^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.aarch64.stderr b/tests/ui/abi/unsupported.aarch64.stderr index 4721c26026d1..61d07f29fd74 100644 --- a/tests/ui/abi/unsupported.aarch64.stderr +++ b/tests/ui/abi/unsupported.aarch64.stderr @@ -1,136 +1,163 @@ -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:36:8 + | +LL | extern "ptx-kernel" fn ptx() {} + | ^^^^^^^^^^^^ + +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:38:22 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + | ^^^^^^^^^^^^ -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:43:1 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:42:8 | LL | extern "ptx-kernel" {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ -warning: the calling convention "aapcs" is not supported on this target - --> $DIR/unsupported.rs:50:17 +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:44:8 + | +LL | extern "gpu-kernel" fn gpu() {} + | ^^^^^^^^^^^^ + +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:47:8 + | +LL | extern "aapcs" fn aapcs() {} + | ^^^^^^^ + +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:49:24 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 + | ^^^^^^^ -error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:55:1 +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:53:8 | LL | extern "aapcs" {} - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^ -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 - | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:65:1 +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:56:8 | LL | extern "msp430-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 - | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:75:1 +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:59:8 | LL | extern "avr-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ -warning: the calling convention "riscv-interrupt-m" is not supported on this target - --> $DIR/unsupported.rs:80:17 - | -LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:85:1 +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/unsupported.rs:62:8 | LL | extern "riscv-interrupt-m" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ -warning: the calling convention "x86-interrupt" is not supported on this target - --> $DIR/unsupported.rs:90:15 - | -LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:95:1 +error[E0570]: "x86-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:65:8 | LL | extern "x86-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ -warning: the calling convention "thiscall" is not supported on this target - --> $DIR/unsupported.rs:100:20 +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:68:8 + | +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^ + +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:70:27 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 + | ^^^^^^^^^^ -error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:105:1 +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:74:8 | LL | extern "thiscall" {} - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ -warning: the calling convention "stdcall" is not supported on this target - --> $DIR/unsupported.rs:112:19 +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:77:8 | -LL | fn stdcall_ptr(f: extern "stdcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"stdcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:119:1 - | -LL | extern "stdcall" {} - | ^^^^^^^^^^^^^^^^^^^ +LL | extern "stdcall" fn stdcall() {} + | ^^^^^^^^^ | = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` -error[E0570]: `"stdcall-unwind"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:123:1 +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:81:26 + | +LL | fn stdcall_ptr(f: extern "stdcall" fn()) { + | ^^^^^^^^^ + | + = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` + +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:87:8 + | +LL | extern "stdcall" {} + | ^^^^^^^^^ + | + = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` + +error[E0570]: "stdcall-unwind" is not a supported ABI for the current target + --> $DIR/unsupported.rs:91:8 | LL | extern "stdcall-unwind" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: if you need `extern "stdcall-unwind"` on win32 and `extern "C-unwind"` everywhere else, use `extern "system-unwind"` -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:131:17 +error[E0570]: "vectorcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:111:8 + | +LL | extern "vectorcall" fn vectorcall() {} + | ^^^^^^^^^^^^ + +error[E0570]: "vectorcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:113:29 + | +LL | fn vectorcall_ptr(f: extern "vectorcall" fn()) { + | ^^^^^^^^^^^^ + +error[E0570]: "vectorcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:117:8 + | +LL | extern "vectorcall" {} + | ^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-call" is not a supported ABI for the current target + --> $DIR/unsupported.rs:120:28 + | +LL | fn cmse_call_ptr(f: extern "cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:125:8 + | +LL | extern "cmse-nonsecure-entry" fn cmse_entry() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:127:29 + | +LL | fn cmse_entry_ptr(f: extern "cmse-nonsecure-entry" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:131:8 + | +LL | extern "cmse-nonsecure-entry" {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:99:17 | LL | fn cdecl_ptr(f: extern "cdecl" fn()) { | ^^^^^^^^^^^^^^^^^^^ @@ -140,8 +167,8 @@ LL | fn cdecl_ptr(f: extern "cdecl" fn()) { = help: use `extern "C"` instead = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:136:1 +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:104:1 | LL | extern "cdecl" {} | ^^^^^^^^^^^^^^^^^ @@ -150,8 +177,8 @@ LL | extern "cdecl" {} = note: for more information, see issue #137018 = help: use `extern "C"` instead -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:139:1 +warning: "cdecl-unwind" is not a supported ABI for the current target + --> $DIR/unsupported.rs:107:1 | LL | extern "cdecl-unwind" {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,103 +187,8 @@ LL | extern "cdecl-unwind" {} = note: for more information, see issue #137018 = help: use `extern "C-unwind"` instead -warning: the calling convention "vectorcall" is not supported on this target - --> $DIR/unsupported.rs:145:22 - | -LL | fn vectorcall_ptr(f: extern "vectorcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"vectorcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:150:1 - | -LL | extern "vectorcall" {} - | ^^^^^^^^^^^^^^^^^^^^^^ - -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 - | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 - | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:166:1 - | -LL | extern "C-cmse-nonsecure-entry" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 - | -LL | extern "ptx-kernel" fn ptx() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:45:1 - | -LL | extern "gpu-kernel" fn gpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:48:1 - | -LL | extern "aapcs" fn aapcs() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:58:1 - | -LL | extern "msp430-interrupt" fn msp430() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:68:1 - | -LL | extern "avr-interrupt" fn avr() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:78:1 - | -LL | extern "riscv-interrupt-m" fn riscv() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:88:1 - | -LL | extern "x86-interrupt" fn x86() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:98:1 - | -LL | extern "thiscall" fn thiscall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"stdcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:108:1 - | -LL | extern "stdcall" fn stdcall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` - -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:128:1 +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:96:1 | LL | extern "cdecl" fn cdecl() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -265,139 +197,6 @@ LL | extern "cdecl" fn cdecl() {} = note: for more information, see issue #137018 = help: use `extern "C"` instead -error[E0570]: `"vectorcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:143:1 - | -LL | extern "vectorcall" fn vectorcall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:159:1 - | -LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 22 previous errors; 15 warnings emitted +error: aborting due to 25 previous errors; 4 warnings emitted For more information about this error, try `rustc --explain E0570`. -Future incompatibility report: Future breakage diagnostic: -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 - | -LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "aapcs" is not supported on this target - --> $DIR/unsupported.rs:50:17 - | -LL | fn aapcs_ptr(f: extern "aapcs" fn()) { - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 - | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 - | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "riscv-interrupt-m" is not supported on this target - --> $DIR/unsupported.rs:80:17 - | -LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "x86-interrupt" is not supported on this target - --> $DIR/unsupported.rs:90:15 - | -LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "thiscall" is not supported on this target - --> $DIR/unsupported.rs:100:20 - | -LL | fn thiscall_ptr(f: extern "thiscall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "stdcall" is not supported on this target - --> $DIR/unsupported.rs:112:19 - | -LL | fn stdcall_ptr(f: extern "stdcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "vectorcall" is not supported on this target - --> $DIR/unsupported.rs:145:22 - | -LL | fn vectorcall_ptr(f: extern "vectorcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 - | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 - | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - diff --git a/tests/ui/abi/unsupported.arm.stderr b/tests/ui/abi/unsupported.arm.stderr index ed9cd2ab2c5d..37b6e2316b0a 100644 --- a/tests/ui/abi/unsupported.arm.stderr +++ b/tests/ui/abi/unsupported.arm.stderr @@ -1,121 +1,145 @@ -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:36:8 + | +LL | extern "ptx-kernel" fn ptx() {} + | ^^^^^^^^^^^^ + +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:38:22 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + | ^^^^^^^^^^^^ -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:43:1 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:42:8 | LL | extern "ptx-kernel" {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:44:8 | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 +LL | extern "gpu-kernel" fn gpu() {} + | ^^^^^^^^^^^^ -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:65:1 +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:56:8 | LL | extern "msp430-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 - | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:75:1 +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:59:8 | LL | extern "avr-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ -warning: the calling convention "riscv-interrupt-m" is not supported on this target - --> $DIR/unsupported.rs:80:17 - | -LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:85:1 +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/unsupported.rs:62:8 | LL | extern "riscv-interrupt-m" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ -warning: the calling convention "x86-interrupt" is not supported on this target - --> $DIR/unsupported.rs:90:15 - | -LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:95:1 +error[E0570]: "x86-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:65:8 | LL | extern "x86-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ -warning: the calling convention "thiscall" is not supported on this target - --> $DIR/unsupported.rs:100:20 +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:68:8 + | +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^ + +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:70:27 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 + | ^^^^^^^^^^ -error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:105:1 +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:74:8 | LL | extern "thiscall" {} - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ -warning: the calling convention "stdcall" is not supported on this target - --> $DIR/unsupported.rs:112:19 +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:77:8 | -LL | fn stdcall_ptr(f: extern "stdcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"stdcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:119:1 - | -LL | extern "stdcall" {} - | ^^^^^^^^^^^^^^^^^^^ +LL | extern "stdcall" fn stdcall() {} + | ^^^^^^^^^ | = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` -error[E0570]: `"stdcall-unwind"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:123:1 +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:81:26 + | +LL | fn stdcall_ptr(f: extern "stdcall" fn()) { + | ^^^^^^^^^ + | + = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` + +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:87:8 + | +LL | extern "stdcall" {} + | ^^^^^^^^^ + | + = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` + +error[E0570]: "stdcall-unwind" is not a supported ABI for the current target + --> $DIR/unsupported.rs:91:8 | LL | extern "stdcall-unwind" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: if you need `extern "stdcall-unwind"` on win32 and `extern "C-unwind"` everywhere else, use `extern "system-unwind"` -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:131:17 +error[E0570]: "vectorcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:111:8 + | +LL | extern "vectorcall" fn vectorcall() {} + | ^^^^^^^^^^^^ + +error[E0570]: "vectorcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:113:29 + | +LL | fn vectorcall_ptr(f: extern "vectorcall" fn()) { + | ^^^^^^^^^^^^ + +error[E0570]: "vectorcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:117:8 + | +LL | extern "vectorcall" {} + | ^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-call" is not a supported ABI for the current target + --> $DIR/unsupported.rs:120:28 + | +LL | fn cmse_call_ptr(f: extern "cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:125:8 + | +LL | extern "cmse-nonsecure-entry" fn cmse_entry() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:127:29 + | +LL | fn cmse_entry_ptr(f: extern "cmse-nonsecure-entry" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:131:8 + | +LL | extern "cmse-nonsecure-entry" {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:99:17 | LL | fn cdecl_ptr(f: extern "cdecl" fn()) { | ^^^^^^^^^^^^^^^^^^^ @@ -125,8 +149,8 @@ LL | fn cdecl_ptr(f: extern "cdecl" fn()) { = help: use `extern "C"` instead = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:136:1 +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:104:1 | LL | extern "cdecl" {} | ^^^^^^^^^^^^^^^^^ @@ -135,8 +159,8 @@ LL | extern "cdecl" {} = note: for more information, see issue #137018 = help: use `extern "C"` instead -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:139:1 +warning: "cdecl-unwind" is not a supported ABI for the current target + --> $DIR/unsupported.rs:107:1 | LL | extern "cdecl-unwind" {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,97 +169,8 @@ LL | extern "cdecl-unwind" {} = note: for more information, see issue #137018 = help: use `extern "C-unwind"` instead -warning: the calling convention "vectorcall" is not supported on this target - --> $DIR/unsupported.rs:145:22 - | -LL | fn vectorcall_ptr(f: extern "vectorcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"vectorcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:150:1 - | -LL | extern "vectorcall" {} - | ^^^^^^^^^^^^^^^^^^^^^^ - -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 - | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 - | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:166:1 - | -LL | extern "C-cmse-nonsecure-entry" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 - | -LL | extern "ptx-kernel" fn ptx() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:45:1 - | -LL | extern "gpu-kernel" fn gpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:58:1 - | -LL | extern "msp430-interrupt" fn msp430() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:68:1 - | -LL | extern "avr-interrupt" fn avr() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:78:1 - | -LL | extern "riscv-interrupt-m" fn riscv() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:88:1 - | -LL | extern "x86-interrupt" fn x86() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:98:1 - | -LL | extern "thiscall" fn thiscall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"stdcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:108:1 - | -LL | extern "stdcall" fn stdcall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` - -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:128:1 +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:96:1 | LL | extern "cdecl" fn cdecl() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -244,128 +179,6 @@ LL | extern "cdecl" fn cdecl() {} = note: for more information, see issue #137018 = help: use `extern "C"` instead -error[E0570]: `"vectorcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:143:1 - | -LL | extern "vectorcall" fn vectorcall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:159:1 - | -LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 20 previous errors; 14 warnings emitted +error: aborting due to 22 previous errors; 4 warnings emitted For more information about this error, try `rustc --explain E0570`. -Future incompatibility report: Future breakage diagnostic: -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 - | -LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 - | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 - | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "riscv-interrupt-m" is not supported on this target - --> $DIR/unsupported.rs:80:17 - | -LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "x86-interrupt" is not supported on this target - --> $DIR/unsupported.rs:90:15 - | -LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "thiscall" is not supported on this target - --> $DIR/unsupported.rs:100:20 - | -LL | fn thiscall_ptr(f: extern "thiscall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "stdcall" is not supported on this target - --> $DIR/unsupported.rs:112:19 - | -LL | fn stdcall_ptr(f: extern "stdcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "vectorcall" is not supported on this target - --> $DIR/unsupported.rs:145:22 - | -LL | fn vectorcall_ptr(f: extern "vectorcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 - | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 - | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - diff --git a/tests/ui/abi/unsupported.i686.stderr b/tests/ui/abi/unsupported.i686.stderr index 4d903b435d87..8478c4819416 100644 --- a/tests/ui/abi/unsupported.i686.stderr +++ b/tests/ui/abi/unsupported.i686.stderr @@ -1,222 +1,87 @@ -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 - | -LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:43:1 - | -LL | extern "ptx-kernel" {} - | ^^^^^^^^^^^^^^^^^^^^^^ - -warning: the calling convention "aapcs" is not supported on this target - --> $DIR/unsupported.rs:50:17 - | -LL | fn aapcs_ptr(f: extern "aapcs" fn()) { - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:55:1 - | -LL | extern "aapcs" {} - | ^^^^^^^^^^^^^^^^^ - -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 - | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:65:1 - | -LL | extern "msp430-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 - | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:75:1 - | -LL | extern "avr-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: the calling convention "riscv-interrupt-m" is not supported on this target - --> $DIR/unsupported.rs:80:17 - | -LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:85:1 - | -LL | extern "riscv-interrupt-m" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 - | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 - | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:166:1 - | -LL | extern "C-cmse-nonsecure-entry" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:36:8 | LL | extern "ptx-kernel" fn ptx() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ -error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:45:1 - | -LL | extern "gpu-kernel" fn gpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:48:1 - | -LL | extern "aapcs" fn aapcs() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:58:1 - | -LL | extern "msp430-interrupt" fn msp430() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:68:1 - | -LL | extern "avr-interrupt" fn avr() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:78:1 - | -LL | extern "riscv-interrupt-m" fn riscv() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:159:1 - | -LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 13 previous errors; 7 warnings emitted - -For more information about this error, try `rustc --explain E0570`. -Future incompatibility report: Future breakage diagnostic: -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:38:22 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + | ^^^^^^^^^^^^ -Future breakage diagnostic: -warning: the calling convention "aapcs" is not supported on this target - --> $DIR/unsupported.rs:50:17 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:42:8 + | +LL | extern "ptx-kernel" {} + | ^^^^^^^^^^^^ + +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:44:8 + | +LL | extern "gpu-kernel" fn gpu() {} + | ^^^^^^^^^^^^ + +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:47:8 + | +LL | extern "aapcs" fn aapcs() {} + | ^^^^^^^ + +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:49:24 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + | ^^^^^^^ -Future breakage diagnostic: -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:53:8 | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default +LL | extern "aapcs" {} + | ^^^^^^^ -Future breakage diagnostic: -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:56:8 | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default +LL | extern "msp430-interrupt" {} + | ^^^^^^^^^^^^^^^^^^ -Future breakage diagnostic: -warning: the calling convention "riscv-interrupt-m" is not supported on this target - --> $DIR/unsupported.rs:80:17 +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:59:8 | -LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default +LL | extern "avr-interrupt" {} + | ^^^^^^^^^^^^^^^ -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/unsupported.rs:62:8 | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default +LL | extern "riscv-interrupt-m" {} + | ^^^^^^^^^^^^^^^^^^^ -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 +error[E0570]: "cmse-nonsecure-call" is not a supported ABI for the current target + --> $DIR/unsupported.rs:120:28 | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default +LL | fn cmse_call_ptr(f: extern "cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^ +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:125:8 + | +LL | extern "cmse-nonsecure-entry" fn cmse_entry() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:127:29 + | +LL | fn cmse_entry_ptr(f: extern "cmse-nonsecure-entry" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:131:8 + | +LL | extern "cmse-nonsecure-entry" {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.riscv32.stderr b/tests/ui/abi/unsupported.riscv32.stderr index 9e75dfafca0f..d7eb222eb766 100644 --- a/tests/ui/abi/unsupported.riscv32.stderr +++ b/tests/ui/abi/unsupported.riscv32.stderr @@ -1,121 +1,157 @@ -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:36:8 + | +LL | extern "ptx-kernel" fn ptx() {} + | ^^^^^^^^^^^^ + +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:38:22 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + | ^^^^^^^^^^^^ -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:43:1 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:42:8 | LL | extern "ptx-kernel" {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ -warning: the calling convention "aapcs" is not supported on this target - --> $DIR/unsupported.rs:50:17 +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:44:8 + | +LL | extern "gpu-kernel" fn gpu() {} + | ^^^^^^^^^^^^ + +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:47:8 + | +LL | extern "aapcs" fn aapcs() {} + | ^^^^^^^ + +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:49:24 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 + | ^^^^^^^ -error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:55:1 +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:53:8 | LL | extern "aapcs" {} - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^ -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 - | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:65:1 +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:56:8 | LL | extern "msp430-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 - | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:75:1 +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:59:8 | LL | extern "avr-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ -warning: the calling convention "x86-interrupt" is not supported on this target - --> $DIR/unsupported.rs:90:15 - | -LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:95:1 +error[E0570]: "x86-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:65:8 | LL | extern "x86-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ -warning: the calling convention "thiscall" is not supported on this target - --> $DIR/unsupported.rs:100:20 +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:68:8 + | +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^ + +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:70:27 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 + | ^^^^^^^^^^ -error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:105:1 +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:74:8 | LL | extern "thiscall" {} - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ -warning: the calling convention "stdcall" is not supported on this target - --> $DIR/unsupported.rs:112:19 +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:77:8 | -LL | fn stdcall_ptr(f: extern "stdcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"stdcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:119:1 - | -LL | extern "stdcall" {} - | ^^^^^^^^^^^^^^^^^^^ +LL | extern "stdcall" fn stdcall() {} + | ^^^^^^^^^ | = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` -error[E0570]: `"stdcall-unwind"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:123:1 +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:81:26 + | +LL | fn stdcall_ptr(f: extern "stdcall" fn()) { + | ^^^^^^^^^ + | + = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` + +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:87:8 + | +LL | extern "stdcall" {} + | ^^^^^^^^^ + | + = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` + +error[E0570]: "stdcall-unwind" is not a supported ABI for the current target + --> $DIR/unsupported.rs:91:8 | LL | extern "stdcall-unwind" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: if you need `extern "stdcall-unwind"` on win32 and `extern "C-unwind"` everywhere else, use `extern "system-unwind"` -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:131:17 +error[E0570]: "vectorcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:111:8 + | +LL | extern "vectorcall" fn vectorcall() {} + | ^^^^^^^^^^^^ + +error[E0570]: "vectorcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:113:29 + | +LL | fn vectorcall_ptr(f: extern "vectorcall" fn()) { + | ^^^^^^^^^^^^ + +error[E0570]: "vectorcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:117:8 + | +LL | extern "vectorcall" {} + | ^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-call" is not a supported ABI for the current target + --> $DIR/unsupported.rs:120:28 + | +LL | fn cmse_call_ptr(f: extern "cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:125:8 + | +LL | extern "cmse-nonsecure-entry" fn cmse_entry() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:127:29 + | +LL | fn cmse_entry_ptr(f: extern "cmse-nonsecure-entry" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:131:8 + | +LL | extern "cmse-nonsecure-entry" {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:99:17 | LL | fn cdecl_ptr(f: extern "cdecl" fn()) { | ^^^^^^^^^^^^^^^^^^^ @@ -125,8 +161,8 @@ LL | fn cdecl_ptr(f: extern "cdecl" fn()) { = help: use `extern "C"` instead = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:136:1 +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:104:1 | LL | extern "cdecl" {} | ^^^^^^^^^^^^^^^^^ @@ -135,8 +171,8 @@ LL | extern "cdecl" {} = note: for more information, see issue #137018 = help: use `extern "C"` instead -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:139:1 +warning: "cdecl-unwind" is not a supported ABI for the current target + --> $DIR/unsupported.rs:107:1 | LL | extern "cdecl-unwind" {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,97 +181,8 @@ LL | extern "cdecl-unwind" {} = note: for more information, see issue #137018 = help: use `extern "C-unwind"` instead -warning: the calling convention "vectorcall" is not supported on this target - --> $DIR/unsupported.rs:145:22 - | -LL | fn vectorcall_ptr(f: extern "vectorcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"vectorcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:150:1 - | -LL | extern "vectorcall" {} - | ^^^^^^^^^^^^^^^^^^^^^^ - -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 - | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 - | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:166:1 - | -LL | extern "C-cmse-nonsecure-entry" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 - | -LL | extern "ptx-kernel" fn ptx() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:45:1 - | -LL | extern "gpu-kernel" fn gpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:48:1 - | -LL | extern "aapcs" fn aapcs() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:58:1 - | -LL | extern "msp430-interrupt" fn msp430() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:68:1 - | -LL | extern "avr-interrupt" fn avr() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:88:1 - | -LL | extern "x86-interrupt" fn x86() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:98:1 - | -LL | extern "thiscall" fn thiscall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"stdcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:108:1 - | -LL | extern "stdcall" fn stdcall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` - -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:128:1 +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:96:1 | LL | extern "cdecl" fn cdecl() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -244,128 +191,6 @@ LL | extern "cdecl" fn cdecl() {} = note: for more information, see issue #137018 = help: use `extern "C"` instead -error[E0570]: `"vectorcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:143:1 - | -LL | extern "vectorcall" fn vectorcall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:159:1 - | -LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 20 previous errors; 14 warnings emitted +error: aborting due to 24 previous errors; 4 warnings emitted For more information about this error, try `rustc --explain E0570`. -Future incompatibility report: Future breakage diagnostic: -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 - | -LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "aapcs" is not supported on this target - --> $DIR/unsupported.rs:50:17 - | -LL | fn aapcs_ptr(f: extern "aapcs" fn()) { - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 - | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 - | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "x86-interrupt" is not supported on this target - --> $DIR/unsupported.rs:90:15 - | -LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "thiscall" is not supported on this target - --> $DIR/unsupported.rs:100:20 - | -LL | fn thiscall_ptr(f: extern "thiscall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "stdcall" is not supported on this target - --> $DIR/unsupported.rs:112:19 - | -LL | fn stdcall_ptr(f: extern "stdcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "vectorcall" is not supported on this target - --> $DIR/unsupported.rs:145:22 - | -LL | fn vectorcall_ptr(f: extern "vectorcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 - | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 - | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - diff --git a/tests/ui/abi/unsupported.riscv64.stderr b/tests/ui/abi/unsupported.riscv64.stderr index 9e75dfafca0f..d7eb222eb766 100644 --- a/tests/ui/abi/unsupported.riscv64.stderr +++ b/tests/ui/abi/unsupported.riscv64.stderr @@ -1,121 +1,157 @@ -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:36:8 + | +LL | extern "ptx-kernel" fn ptx() {} + | ^^^^^^^^^^^^ + +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:38:22 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + | ^^^^^^^^^^^^ -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:43:1 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:42:8 | LL | extern "ptx-kernel" {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ -warning: the calling convention "aapcs" is not supported on this target - --> $DIR/unsupported.rs:50:17 +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:44:8 + | +LL | extern "gpu-kernel" fn gpu() {} + | ^^^^^^^^^^^^ + +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:47:8 + | +LL | extern "aapcs" fn aapcs() {} + | ^^^^^^^ + +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:49:24 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 + | ^^^^^^^ -error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:55:1 +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:53:8 | LL | extern "aapcs" {} - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^ -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 - | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:65:1 +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:56:8 | LL | extern "msp430-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 - | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:75:1 +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:59:8 | LL | extern "avr-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ -warning: the calling convention "x86-interrupt" is not supported on this target - --> $DIR/unsupported.rs:90:15 - | -LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:95:1 +error[E0570]: "x86-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:65:8 | LL | extern "x86-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ -warning: the calling convention "thiscall" is not supported on this target - --> $DIR/unsupported.rs:100:20 +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:68:8 + | +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^ + +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:70:27 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 + | ^^^^^^^^^^ -error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:105:1 +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:74:8 | LL | extern "thiscall" {} - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ -warning: the calling convention "stdcall" is not supported on this target - --> $DIR/unsupported.rs:112:19 +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:77:8 | -LL | fn stdcall_ptr(f: extern "stdcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"stdcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:119:1 - | -LL | extern "stdcall" {} - | ^^^^^^^^^^^^^^^^^^^ +LL | extern "stdcall" fn stdcall() {} + | ^^^^^^^^^ | = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` -error[E0570]: `"stdcall-unwind"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:123:1 +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:81:26 + | +LL | fn stdcall_ptr(f: extern "stdcall" fn()) { + | ^^^^^^^^^ + | + = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` + +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:87:8 + | +LL | extern "stdcall" {} + | ^^^^^^^^^ + | + = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` + +error[E0570]: "stdcall-unwind" is not a supported ABI for the current target + --> $DIR/unsupported.rs:91:8 | LL | extern "stdcall-unwind" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: if you need `extern "stdcall-unwind"` on win32 and `extern "C-unwind"` everywhere else, use `extern "system-unwind"` -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:131:17 +error[E0570]: "vectorcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:111:8 + | +LL | extern "vectorcall" fn vectorcall() {} + | ^^^^^^^^^^^^ + +error[E0570]: "vectorcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:113:29 + | +LL | fn vectorcall_ptr(f: extern "vectorcall" fn()) { + | ^^^^^^^^^^^^ + +error[E0570]: "vectorcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:117:8 + | +LL | extern "vectorcall" {} + | ^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-call" is not a supported ABI for the current target + --> $DIR/unsupported.rs:120:28 + | +LL | fn cmse_call_ptr(f: extern "cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:125:8 + | +LL | extern "cmse-nonsecure-entry" fn cmse_entry() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:127:29 + | +LL | fn cmse_entry_ptr(f: extern "cmse-nonsecure-entry" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:131:8 + | +LL | extern "cmse-nonsecure-entry" {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:99:17 | LL | fn cdecl_ptr(f: extern "cdecl" fn()) { | ^^^^^^^^^^^^^^^^^^^ @@ -125,8 +161,8 @@ LL | fn cdecl_ptr(f: extern "cdecl" fn()) { = help: use `extern "C"` instead = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:136:1 +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:104:1 | LL | extern "cdecl" {} | ^^^^^^^^^^^^^^^^^ @@ -135,8 +171,8 @@ LL | extern "cdecl" {} = note: for more information, see issue #137018 = help: use `extern "C"` instead -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:139:1 +warning: "cdecl-unwind" is not a supported ABI for the current target + --> $DIR/unsupported.rs:107:1 | LL | extern "cdecl-unwind" {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,97 +181,8 @@ LL | extern "cdecl-unwind" {} = note: for more information, see issue #137018 = help: use `extern "C-unwind"` instead -warning: the calling convention "vectorcall" is not supported on this target - --> $DIR/unsupported.rs:145:22 - | -LL | fn vectorcall_ptr(f: extern "vectorcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"vectorcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:150:1 - | -LL | extern "vectorcall" {} - | ^^^^^^^^^^^^^^^^^^^^^^ - -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 - | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 - | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:166:1 - | -LL | extern "C-cmse-nonsecure-entry" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 - | -LL | extern "ptx-kernel" fn ptx() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:45:1 - | -LL | extern "gpu-kernel" fn gpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:48:1 - | -LL | extern "aapcs" fn aapcs() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:58:1 - | -LL | extern "msp430-interrupt" fn msp430() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:68:1 - | -LL | extern "avr-interrupt" fn avr() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:88:1 - | -LL | extern "x86-interrupt" fn x86() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:98:1 - | -LL | extern "thiscall" fn thiscall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"stdcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:108:1 - | -LL | extern "stdcall" fn stdcall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` - -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:128:1 +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:96:1 | LL | extern "cdecl" fn cdecl() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -244,128 +191,6 @@ LL | extern "cdecl" fn cdecl() {} = note: for more information, see issue #137018 = help: use `extern "C"` instead -error[E0570]: `"vectorcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:143:1 - | -LL | extern "vectorcall" fn vectorcall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:159:1 - | -LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 20 previous errors; 14 warnings emitted +error: aborting due to 24 previous errors; 4 warnings emitted For more information about this error, try `rustc --explain E0570`. -Future incompatibility report: Future breakage diagnostic: -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 - | -LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "aapcs" is not supported on this target - --> $DIR/unsupported.rs:50:17 - | -LL | fn aapcs_ptr(f: extern "aapcs" fn()) { - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 - | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 - | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "x86-interrupt" is not supported on this target - --> $DIR/unsupported.rs:90:15 - | -LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "thiscall" is not supported on this target - --> $DIR/unsupported.rs:100:20 - | -LL | fn thiscall_ptr(f: extern "thiscall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "stdcall" is not supported on this target - --> $DIR/unsupported.rs:112:19 - | -LL | fn stdcall_ptr(f: extern "stdcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "vectorcall" is not supported on this target - --> $DIR/unsupported.rs:145:22 - | -LL | fn vectorcall_ptr(f: extern "vectorcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 - | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 - | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - diff --git a/tests/ui/abi/unsupported.rs b/tests/ui/abi/unsupported.rs index 43bdfe3ea240..828fcc147a56 100644 --- a/tests/ui/abi/unsupported.rs +++ b/tests/ui/abi/unsupported.rs @@ -25,7 +25,7 @@ abi_gpu_kernel, abi_x86_interrupt, abi_riscv_interrupt, - abi_c_cmse_nonsecure_call, + abi_cmse_nonsecure_call, abi_vectorcall, cmse_nonsecure_entry )] @@ -36,8 +36,7 @@ use minicore::*; extern "ptx-kernel" fn ptx() {} //~^ ERROR is not a supported ABI fn ptx_ptr(f: extern "ptx-kernel" fn()) { - //~^ WARN unsupported_fn_ptr_calling_conventions - //~^^ WARN this was previously accepted +//~^ ERROR is not a supported ABI f() } extern "ptx-kernel" {} @@ -48,58 +47,28 @@ extern "gpu-kernel" fn gpu() {} extern "aapcs" fn aapcs() {} //[x64,x64_win,i686,aarch64,riscv32,riscv64]~^ ERROR is not a supported ABI fn aapcs_ptr(f: extern "aapcs" fn()) { - //[x64,x64_win,i686,aarch64,riscv32,riscv64]~^ WARN unsupported_fn_ptr_calling_conventions - //[x64,x64_win,i686,aarch64,riscv32,riscv64]~^^ WARN this was previously accepted + //[x64,x64_win,i686,aarch64,riscv32,riscv64]~^ ERROR is not a supported ABI f() } extern "aapcs" {} //[x64,x64_win,i686,aarch64,riscv32,riscv64]~^ ERROR is not a supported ABI -extern "msp430-interrupt" fn msp430() {} -//~^ ERROR is not a supported ABI -fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - //~^ WARN unsupported_fn_ptr_calling_conventions - //~^^ WARN this was previously accepted - f() -} extern "msp430-interrupt" {} //~^ ERROR is not a supported ABI -extern "avr-interrupt" fn avr() {} -//~^ ERROR is not a supported ABI -fn avr_ptr(f: extern "avr-interrupt" fn()) { - //~^ WARN unsupported_fn_ptr_calling_conventions - //~^^ WARN this was previously accepted - f() -} extern "avr-interrupt" {} //~^ ERROR is not a supported ABI -extern "riscv-interrupt-m" fn riscv() {} -//[x64,x64_win,i686,arm,aarch64]~^ ERROR is not a supported ABI -fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { - //[x64,x64_win,i686,arm,aarch64]~^ WARN unsupported_fn_ptr_calling_conventions - //[x64,x64_win,i686,arm,aarch64]~^^ WARN this was previously accepted - f() -} extern "riscv-interrupt-m" {} //[x64,x64_win,i686,arm,aarch64]~^ ERROR is not a supported ABI -extern "x86-interrupt" fn x86() {} -//[aarch64,arm,riscv32,riscv64]~^ ERROR is not a supported ABI -fn x86_ptr(f: extern "x86-interrupt" fn()) { - //[aarch64,arm,riscv32,riscv64]~^ WARN unsupported_fn_ptr_calling_conventions - //[aarch64,arm,riscv32,riscv64]~^^ WARN this was previously accepted - f() -} extern "x86-interrupt" {} //[aarch64,arm,riscv32,riscv64]~^ ERROR is not a supported ABI extern "thiscall" fn thiscall() {} //[x64,x64_win,arm,aarch64,riscv32,riscv64]~^ ERROR is not a supported ABI fn thiscall_ptr(f: extern "thiscall" fn()) { - //[x64,x64_win,arm,aarch64,riscv32,riscv64]~^ WARN unsupported_fn_ptr_calling_conventions - //[x64,x64_win,arm,aarch64,riscv32,riscv64]~^^ WARN this was previously accepted + //[x64,x64_win,arm,aarch64,riscv32,riscv64]~^ ERROR is not a supported ABI f() } extern "thiscall" {} @@ -110,10 +79,9 @@ extern "stdcall" fn stdcall() {} //[x64_win]~^^ WARN unsupported_calling_conventions //[x64_win]~^^^ WARN this was previously accepted fn stdcall_ptr(f: extern "stdcall" fn()) { - //[x64_win]~^ WARN unsupported_calling_conventions - //[x64_win]~| WARN this was previously accepted - //[x64,arm,aarch64,riscv32,riscv64]~^^^ WARN unsupported_fn_ptr_calling_conventions - //[x64,arm,aarch64,riscv32,riscv64]~| WARN this was previously accepted + //[x64,arm,aarch64,riscv32,riscv64]~^ ERROR is not a supported ABI + //[x64_win]~^^ WARN unsupported_calling_conventions + //[x64_win]~| WARN this was previously accepted f() } extern "stdcall" {} @@ -130,7 +98,7 @@ extern "cdecl" fn cdecl() {} //[x64,x64_win,arm,aarch64,riscv32,riscv64]~^^ WARN this was previously accepted fn cdecl_ptr(f: extern "cdecl" fn()) { //[x64,x64_win,arm,aarch64,riscv32,riscv64]~^ WARN unsupported_calling_conventions - //[x64,x64_win,arm,aarch64,riscv32,riscv64]~^^ WARN this was previously accepted + //[x64,x64_win,arm,aarch64,riscv32,riscv64]~| WARN this was previously accepted f() } extern "cdecl" {} @@ -143,31 +111,28 @@ extern "cdecl-unwind" {} extern "vectorcall" fn vectorcall() {} //[arm,aarch64,riscv32,riscv64]~^ ERROR is not a supported ABI fn vectorcall_ptr(f: extern "vectorcall" fn()) { - //[arm,aarch64,riscv32,riscv64]~^ WARN unsupported_fn_ptr_calling_conventions - //[arm,aarch64,riscv32,riscv64]~^^ WARN this was previously accepted + //[arm,aarch64,riscv32,riscv64]~^ ERROR is not a supported ABI f() } extern "vectorcall" {} //[arm,aarch64,riscv32,riscv64]~^ ERROR is not a supported ABI -fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - //~^ WARN unsupported_fn_ptr_calling_conventions - //~^^ WARN this was previously accepted +fn cmse_call_ptr(f: extern "cmse-nonsecure-call" fn()) { +//~^ ERROR is not a supported ABI f() } -extern "C-cmse-nonsecure-entry" fn cmse_entry() {} +extern "cmse-nonsecure-entry" fn cmse_entry() {} +//~^ ERROR is not a supported ABI +fn cmse_entry_ptr(f: extern "cmse-nonsecure-entry" fn()) { //~^ ERROR is not a supported ABI -fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - //~^ WARN unsupported_fn_ptr_calling_conventions - //~^^ WARN this was previously accepted f() } -extern "C-cmse-nonsecure-entry" {} +extern "cmse-nonsecure-entry" {} //~^ ERROR is not a supported ABI #[cfg(windows)] #[link(name = "foo", kind = "raw-dylib")] extern "cdecl" {} -//[x64_win]~^ WARN use of calling convention not supported on this target +//[x64_win]~^ WARN unsupported_calling_conventions //[x64_win]~^^ WARN this was previously accepted diff --git a/tests/ui/abi/unsupported.x64.stderr b/tests/ui/abi/unsupported.x64.stderr index 5b55e5707fad..cf04680b5878 100644 --- a/tests/ui/abi/unsupported.x64.stderr +++ b/tests/ui/abi/unsupported.x64.stderr @@ -1,121 +1,139 @@ -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:36:8 + | +LL | extern "ptx-kernel" fn ptx() {} + | ^^^^^^^^^^^^ + +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:38:22 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + | ^^^^^^^^^^^^ -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:43:1 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:42:8 | LL | extern "ptx-kernel" {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ -warning: the calling convention "aapcs" is not supported on this target - --> $DIR/unsupported.rs:50:17 +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:44:8 + | +LL | extern "gpu-kernel" fn gpu() {} + | ^^^^^^^^^^^^ + +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:47:8 + | +LL | extern "aapcs" fn aapcs() {} + | ^^^^^^^ + +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:49:24 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 + | ^^^^^^^ -error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:55:1 +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:53:8 | LL | extern "aapcs" {} - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^ -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 - | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:65:1 +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:56:8 | LL | extern "msp430-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 - | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:75:1 +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:59:8 | LL | extern "avr-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ -warning: the calling convention "riscv-interrupt-m" is not supported on this target - --> $DIR/unsupported.rs:80:17 - | -LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:85:1 +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/unsupported.rs:62:8 | LL | extern "riscv-interrupt-m" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ -warning: the calling convention "thiscall" is not supported on this target - --> $DIR/unsupported.rs:100:20 +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:68:8 + | +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^ + +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:70:27 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 + | ^^^^^^^^^^ -error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:105:1 +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:74:8 | LL | extern "thiscall" {} - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ -warning: the calling convention "stdcall" is not supported on this target - --> $DIR/unsupported.rs:112:19 +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:77:8 | -LL | fn stdcall_ptr(f: extern "stdcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"stdcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:119:1 - | -LL | extern "stdcall" {} - | ^^^^^^^^^^^^^^^^^^^ +LL | extern "stdcall" fn stdcall() {} + | ^^^^^^^^^ | = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` -error[E0570]: `"stdcall-unwind"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:123:1 +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:81:26 + | +LL | fn stdcall_ptr(f: extern "stdcall" fn()) { + | ^^^^^^^^^ + | + = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` + +error[E0570]: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:87:8 + | +LL | extern "stdcall" {} + | ^^^^^^^^^ + | + = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` + +error[E0570]: "stdcall-unwind" is not a supported ABI for the current target + --> $DIR/unsupported.rs:91:8 | LL | extern "stdcall-unwind" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: if you need `extern "stdcall-unwind"` on win32 and `extern "C-unwind"` everywhere else, use `extern "system-unwind"` -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:131:17 +error[E0570]: "cmse-nonsecure-call" is not a supported ABI for the current target + --> $DIR/unsupported.rs:120:28 + | +LL | fn cmse_call_ptr(f: extern "cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:125:8 + | +LL | extern "cmse-nonsecure-entry" fn cmse_entry() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:127:29 + | +LL | fn cmse_entry_ptr(f: extern "cmse-nonsecure-entry" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:131:8 + | +LL | extern "cmse-nonsecure-entry" {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:99:17 | LL | fn cdecl_ptr(f: extern "cdecl" fn()) { | ^^^^^^^^^^^^^^^^^^^ @@ -125,8 +143,8 @@ LL | fn cdecl_ptr(f: extern "cdecl" fn()) { = help: use `extern "C"` instead = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:136:1 +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:104:1 | LL | extern "cdecl" {} | ^^^^^^^^^^^^^^^^^ @@ -135,8 +153,8 @@ LL | extern "cdecl" {} = note: for more information, see issue #137018 = help: use `extern "C"` instead -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:139:1 +warning: "cdecl-unwind" is not a supported ABI for the current target + --> $DIR/unsupported.rs:107:1 | LL | extern "cdecl-unwind" {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,82 +163,8 @@ LL | extern "cdecl-unwind" {} = note: for more information, see issue #137018 = help: use `extern "C-unwind"` instead -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 - | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 - | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:166:1 - | -LL | extern "C-cmse-nonsecure-entry" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 - | -LL | extern "ptx-kernel" fn ptx() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:45:1 - | -LL | extern "gpu-kernel" fn gpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:48:1 - | -LL | extern "aapcs" fn aapcs() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:58:1 - | -LL | extern "msp430-interrupt" fn msp430() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:68:1 - | -LL | extern "avr-interrupt" fn avr() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:78:1 - | -LL | extern "riscv-interrupt-m" fn riscv() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:98:1 - | -LL | extern "thiscall" fn thiscall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"stdcall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:108:1 - | -LL | extern "stdcall" fn stdcall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` - -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:128:1 +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:96:1 | LL | extern "cdecl" fn cdecl() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,111 +173,6 @@ LL | extern "cdecl" fn cdecl() {} = note: for more information, see issue #137018 = help: use `extern "C"` instead -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:159:1 - | -LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 18 previous errors; 13 warnings emitted +error: aborting due to 21 previous errors; 4 warnings emitted For more information about this error, try `rustc --explain E0570`. -Future incompatibility report: Future breakage diagnostic: -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 - | -LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "aapcs" is not supported on this target - --> $DIR/unsupported.rs:50:17 - | -LL | fn aapcs_ptr(f: extern "aapcs" fn()) { - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 - | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 - | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "riscv-interrupt-m" is not supported on this target - --> $DIR/unsupported.rs:80:17 - | -LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "thiscall" is not supported on this target - --> $DIR/unsupported.rs:100:20 - | -LL | fn thiscall_ptr(f: extern "thiscall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "stdcall" is not supported on this target - --> $DIR/unsupported.rs:112:19 - | -LL | fn stdcall_ptr(f: extern "stdcall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 - | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 - | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - diff --git a/tests/ui/abi/unsupported.x64_win.stderr b/tests/ui/abi/unsupported.x64_win.stderr index 93b5a272e926..d383a4df732f 100644 --- a/tests/ui/abi/unsupported.x64_win.stderr +++ b/tests/ui/abi/unsupported.x64_win.stderr @@ -1,96 +1,107 @@ -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:36:8 + | +LL | extern "ptx-kernel" fn ptx() {} + | ^^^^^^^^^^^^ + +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:38:22 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + | ^^^^^^^^^^^^ -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:43:1 +error[E0570]: "ptx-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:42:8 | LL | extern "ptx-kernel" {} - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ -warning: the calling convention "aapcs" is not supported on this target - --> $DIR/unsupported.rs:50:17 +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/unsupported.rs:44:8 + | +LL | extern "gpu-kernel" fn gpu() {} + | ^^^^^^^^^^^^ + +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:47:8 + | +LL | extern "aapcs" fn aapcs() {} + | ^^^^^^^ + +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:49:24 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 + | ^^^^^^^ -error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:55:1 +error[E0570]: "aapcs" is not a supported ABI for the current target + --> $DIR/unsupported.rs:53:8 | LL | extern "aapcs" {} - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^ -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 - | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:65:1 +error[E0570]: "msp430-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:56:8 | LL | extern "msp430-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 - | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:75:1 +error[E0570]: "avr-interrupt" is not a supported ABI for the current target + --> $DIR/unsupported.rs:59:8 | LL | extern "avr-interrupt" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ -warning: the calling convention "riscv-interrupt-m" is not supported on this target - --> $DIR/unsupported.rs:80:17 - | -LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:85:1 +error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target + --> $DIR/unsupported.rs:62:8 | LL | extern "riscv-interrupt-m" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ -warning: the calling convention "thiscall" is not supported on this target - --> $DIR/unsupported.rs:100:20 +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:68:8 + | +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^ + +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:70:27 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 + | ^^^^^^^^^^ -error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:105:1 +error[E0570]: "thiscall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:74:8 | LL | extern "thiscall" {} - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:112:19 +error[E0570]: "cmse-nonsecure-call" is not a supported ABI for the current target + --> $DIR/unsupported.rs:120:28 + | +LL | fn cmse_call_ptr(f: extern "cmse-nonsecure-call" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:125:8 + | +LL | extern "cmse-nonsecure-entry" fn cmse_entry() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:127:29 + | +LL | fn cmse_entry_ptr(f: extern "cmse-nonsecure-entry" fn()) { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/unsupported.rs:131:8 + | +LL | extern "cmse-nonsecure-entry" {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:81:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { | ^^^^^^^^^^^^^^^^^^^^^ @@ -100,8 +111,8 @@ LL | fn stdcall_ptr(f: extern "stdcall" fn()) { = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:119:1 +warning: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:87:1 | LL | extern "stdcall" {} | ^^^^^^^^^^^^^^^^^^^ @@ -110,8 +121,8 @@ LL | extern "stdcall" {} = note: for more information, see issue #137018 = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:123:1 +warning: "stdcall-unwind" is not a supported ABI for the current target + --> $DIR/unsupported.rs:91:1 | LL | extern "stdcall-unwind" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -120,8 +131,8 @@ LL | extern "stdcall-unwind" {} = note: for more information, see issue #137018 = help: if you need `extern "stdcall-unwind"` on win32 and `extern "C-unwind"` everywhere else, use `extern "system-unwind"` -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:131:17 +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:99:17 | LL | fn cdecl_ptr(f: extern "cdecl" fn()) { | ^^^^^^^^^^^^^^^^^^^ @@ -130,7 +141,27 @@ LL | fn cdecl_ptr(f: extern "cdecl" fn()) { = note: for more information, see issue #137018 = help: use `extern "C"` instead -warning: use of calling convention not supported on this target +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:104:1 + | +LL | extern "cdecl" {} + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #137018 + = help: use `extern "C"` instead + +warning: "cdecl-unwind" is not a supported ABI for the current target + --> $DIR/unsupported.rs:107:1 + | +LL | extern "cdecl-unwind" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #137018 + = help: use `extern "C-unwind"` instead + +warning: "cdecl" is not a supported ABI for the current target --> $DIR/unsupported.rs:136:1 | LL | extern "cdecl" {} @@ -140,94 +171,8 @@ LL | extern "cdecl" {} = note: for more information, see issue #137018 = help: use `extern "C"` instead -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:139:1 - | -LL | extern "cdecl-unwind" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #137018 - = help: use `extern "C-unwind"` instead - -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 - | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 - | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:166:1 - | -LL | extern "C-cmse-nonsecure-entry" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:171:1 - | -LL | extern "cdecl" {} - | ^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #137018 - = help: use `extern "C"` instead - -error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 - | -LL | extern "ptx-kernel" fn ptx() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:45:1 - | -LL | extern "gpu-kernel" fn gpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:48:1 - | -LL | extern "aapcs" fn aapcs() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:58:1 - | -LL | extern "msp430-interrupt" fn msp430() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:68:1 - | -LL | extern "avr-interrupt" fn avr() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:78:1 - | -LL | extern "riscv-interrupt-m" fn riscv() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:98:1 - | -LL | extern "thiscall" fn thiscall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:108:1 +warning: "stdcall" is not a supported ABI for the current target + --> $DIR/unsupported.rs:77:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -236,8 +181,8 @@ LL | extern "stdcall" fn stdcall() {} = note: for more information, see issue #137018 = help: if you need `extern "stdcall"` on win32 and `extern "C"` everywhere else, use `extern "system"` -warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:128:1 +warning: "cdecl" is not a supported ABI for the current target + --> $DIR/unsupported.rs:96:1 | LL | extern "cdecl" fn cdecl() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -246,100 +191,6 @@ LL | extern "cdecl" fn cdecl() {} = note: for more information, see issue #137018 = help: use `extern "C"` instead -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:159:1 - | -LL | extern "C-cmse-nonsecure-entry" fn cmse_entry() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 15 previous errors; 17 warnings emitted +error: aborting due to 17 previous errors; 9 warnings emitted For more information about this error, try `rustc --explain E0570`. -Future incompatibility report: Future breakage diagnostic: -warning: the calling convention "ptx-kernel" is not supported on this target - --> $DIR/unsupported.rs:38:15 - | -LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "aapcs" is not supported on this target - --> $DIR/unsupported.rs:50:17 - | -LL | fn aapcs_ptr(f: extern "aapcs" fn()) { - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "msp430-interrupt" is not supported on this target - --> $DIR/unsupported.rs:60:18 - | -LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "avr-interrupt" is not supported on this target - --> $DIR/unsupported.rs:70:15 - | -LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "riscv-interrupt-m" is not supported on this target - --> $DIR/unsupported.rs:80:17 - | -LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "thiscall" is not supported on this target - --> $DIR/unsupported.rs:100:20 - | -LL | fn thiscall_ptr(f: extern "thiscall" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/unsupported.rs:153:21 - | -LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target - --> $DIR/unsupported.rs:161:22 - | -LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - diff --git a/tests/ui/allocator/no_std-alloc-error-handler-custom.rs b/tests/ui/allocator/no_std-alloc-error-handler-custom.rs index 6bbfb72510d0..1b0f0608fc61 100644 --- a/tests/ui/allocator/no_std-alloc-error-handler-custom.rs +++ b/tests/ui/allocator/no_std-alloc-error-handler-custom.rs @@ -6,13 +6,14 @@ //@ compile-flags:-C panic=abort //@ aux-build:helper.rs -#![feature(rustc_private, lang_items)] +#![feature(rustc_private, lang_items, panic_unwind)] #![feature(alloc_error_handler)] #![no_std] #![no_main] extern crate alloc; extern crate libc; +extern crate unwind; // For _Unwind_Resume // ARM targets need these symbols #[no_mangle] @@ -70,7 +71,15 @@ fn panic(panic_info: &core::panic::PanicInfo) -> ! { // in these libraries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't // unwind. So, for this test case we will define the symbol. #[lang = "eh_personality"] -extern "C" fn rust_eh_personality() {} +extern "C" fn rust_eh_personality( + _version: i32, + _actions: i32, + _exception_class: u64, + _exception_object: *mut (), + _context: *mut (), +) -> i32 { + loop {} +} #[derive(Default, Debug)] struct Page(#[allow(dead_code)] [[u64; 32]; 16]); diff --git a/tests/ui/allocator/no_std-alloc-error-handler-default.rs b/tests/ui/allocator/no_std-alloc-error-handler-default.rs index 8bcf054ac85f..51ecf1a6731a 100644 --- a/tests/ui/allocator/no_std-alloc-error-handler-default.rs +++ b/tests/ui/allocator/no_std-alloc-error-handler-default.rs @@ -6,12 +6,13 @@ //@ compile-flags:-C panic=abort //@ aux-build:helper.rs -#![feature(rustc_private, lang_items)] +#![feature(rustc_private, lang_items, panic_unwind)] #![no_std] #![no_main] extern crate alloc; extern crate libc; +extern crate unwind; // For _Unwind_Resume // ARM targets need these symbols #[no_mangle] @@ -57,7 +58,15 @@ fn panic(panic_info: &core::panic::PanicInfo) -> ! { // in these libraries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't // unwind. So, for this test case we will define the symbol. #[lang = "eh_personality"] -extern "C" fn rust_eh_personality() {} +extern "C" fn rust_eh_personality( + _version: i32, + _actions: i32, + _exception_class: u64, + _exception_object: *mut (), + _context: *mut (), +) -> i32 { + loop {} +} #[derive(Default, Debug)] struct Page(#[allow(dead_code)] [[u64; 32]; 16]); diff --git a/tests/ui/argument-suggestions/issue-100154.stderr b/tests/ui/argument-suggestions/issue-100154.stderr index 7eaebcafb595..9732beac4492 100644 --- a/tests/ui/argument-suggestions/issue-100154.stderr +++ b/tests/ui/argument-suggestions/issue-100154.stderr @@ -17,10 +17,8 @@ error[E0277]: `()` doesn't implement `std::fmt::Display` --> $DIR/issue-100154.rs:4:11 | LL | foo::<()>(()); - | ^^ `()` cannot be formatted with the default formatter + | ^^ the trait `std::fmt::Display` is not implemented for `()` | - = help: the trait `std::fmt::Display` is not implemented for `()` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `foo` --> $DIR/issue-100154.rs:1:16 | diff --git a/tests/ui/argument-suggestions/issue-100478.rs b/tests/ui/argument-suggestions/issue-100478.rs index b0a9703112e3..219870f3b237 100644 --- a/tests/ui/argument-suggestions/issue-100478.rs +++ b/tests/ui/argument-suggestions/issue-100478.rs @@ -32,8 +32,8 @@ fn four_shuffle(_a: T1, _b: T2, _c: T3, _d: T4) {} fn main() { three_diff(T2::new(0)); //~ ERROR function takes - four_shuffle(T3::default(), T4::default(), T1::default(), T2::default()); //~ ERROR 35:5: 35:17: arguments to this function are incorrect [E0308] - four_shuffle(T3::default(), T2::default(), T1::default(), T3::default()); //~ ERROR 36:5: 36:17: arguments to this function are incorrect [E0308] + four_shuffle(T3::default(), T4::default(), T1::default(), T2::default()); //~ ERROR arguments to this function are incorrect [E0308] + four_shuffle(T3::default(), T2::default(), T1::default(), T3::default()); //~ ERROR arguments to this function are incorrect [E0308] let p1 = T1::new(0); let p2 = Arc::new(T2::new(0)); diff --git a/tests/ui/asm/naked-functions-inline.stderr b/tests/ui/asm/naked-functions-inline.stderr index 07d5f3bc49a9..91140a301edc 100644 --- a/tests/ui/asm/naked-functions-inline.stderr +++ b/tests/ui/asm/naked-functions-inline.stderr @@ -1,26 +1,26 @@ error[E0736]: attribute incompatible with `#[unsafe(naked)]` - --> $DIR/naked-functions-inline.rs:12:1 + --> $DIR/naked-functions-inline.rs:12:3 | LL | #[unsafe(naked)] | ---------------- function marked with `#[unsafe(naked)]` here LL | #[inline] - | ^^^^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` + | ^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` error[E0736]: attribute incompatible with `#[unsafe(naked)]` - --> $DIR/naked-functions-inline.rs:19:1 + --> $DIR/naked-functions-inline.rs:19:3 | LL | #[unsafe(naked)] | ---------------- function marked with `#[unsafe(naked)]` here LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` + | ^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` error[E0736]: attribute incompatible with `#[unsafe(naked)]` - --> $DIR/naked-functions-inline.rs:26:1 + --> $DIR/naked-functions-inline.rs:26:3 | LL | #[unsafe(naked)] | ---------------- function marked with `#[unsafe(naked)]` here LL | #[inline(never)] - | ^^^^^^^^^^^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` + | ^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` error[E0736]: attribute incompatible with `#[unsafe(naked)]` --> $DIR/naked-functions-inline.rs:33:19 @@ -28,7 +28,7 @@ error[E0736]: attribute incompatible with `#[unsafe(naked)]` LL | #[unsafe(naked)] | ---------------- function marked with `#[unsafe(naked)]` here LL | #[cfg_attr(all(), inline(never))] - | ^^^^^^^^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` + | ^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` error: aborting due to 4 previous errors diff --git a/tests/ui/asm/naked-invalid-attr.stderr b/tests/ui/asm/naked-invalid-attr.stderr index ef389e7d921b..915b54b3fc23 100644 --- a/tests/ui/asm/naked-invalid-attr.stderr +++ b/tests/ui/asm/naked-invalid-attr.stderr @@ -4,6 +4,15 @@ error[E0433]: failed to resolve: use of unresolved module or unlinked crate `a` LL | #[::a] | ^ use of unresolved module or unlinked crate `a` +error[E0736]: attribute incompatible with `#[unsafe(naked)]` + --> $DIR/naked-invalid-attr.rs:56:3 + | +LL | #[::a] + | ^^^ the `{{root}}::a` attribute is incompatible with `#[unsafe(naked)]` +... +LL | #[unsafe(naked)] + | ---------------- function marked with `#[unsafe(naked)]` here + error: attribute should be applied to a function definition --> $DIR/naked-invalid-attr.rs:13:1 | @@ -33,15 +42,6 @@ LL | #[unsafe(naked)] LL | || {}; | ----- not a function definition -error[E0736]: attribute incompatible with `#[unsafe(naked)]` - --> $DIR/naked-invalid-attr.rs:56:1 - | -LL | #[::a] - | ^^^^^^ the `{{root}}::a` attribute is incompatible with `#[unsafe(naked)]` -... -LL | #[unsafe(naked)] - | ---------------- function marked with `#[unsafe(naked)]` here - error: attribute should be applied to a function definition --> $DIR/naked-invalid-attr.rs:22:5 | diff --git a/tests/ui/asm/naked-with-invalid-repr-attr.rs b/tests/ui/asm/naked-with-invalid-repr-attr.rs index 96eed70dc550..bfbbf29a69ee 100644 --- a/tests/ui/asm/naked-with-invalid-repr-attr.rs +++ b/tests/ui/asm/naked-with-invalid-repr-attr.rs @@ -19,8 +19,9 @@ extern "C" fn example2() { naked_asm!("") } -#[repr(align(16), C)] +#[repr(C)] //~^ ERROR attribute should be applied to a struct, enum, or union [E0517] +#[align(16)] #[unsafe(naked)] extern "C" fn example3() { //~^ NOTE not a struct, enum, or union diff --git a/tests/ui/asm/naked-with-invalid-repr-attr.stderr b/tests/ui/asm/naked-with-invalid-repr-attr.stderr index f173a39e5bf6..4eb4a4e5a048 100644 --- a/tests/ui/asm/naked-with-invalid-repr-attr.stderr +++ b/tests/ui/asm/naked-with-invalid-repr-attr.stderr @@ -23,10 +23,10 @@ LL | | } | |_- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/naked-with-invalid-repr-attr.rs:22:19 + --> $DIR/naked-with-invalid-repr-attr.rs:22:8 | -LL | #[repr(align(16), C)] - | ^ +LL | #[repr(C)] + | ^ ... LL | / extern "C" fn example3() { LL | | @@ -35,7 +35,7 @@ LL | | } | |_- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/naked-with-invalid-repr-attr.rs:31:8 + --> $DIR/naked-with-invalid-repr-attr.rs:32:8 | LL | #[repr(C, packed)] | ^ @@ -48,7 +48,7 @@ LL | | } | |_- not a struct, enum, or union error[E0517]: attribute should be applied to a struct or union - --> $DIR/naked-with-invalid-repr-attr.rs:31:11 + --> $DIR/naked-with-invalid-repr-attr.rs:32:11 | LL | #[repr(C, packed)] | ^^^^^^ @@ -61,7 +61,7 @@ LL | | } | |_- not a struct or union error[E0517]: attribute should be applied to an enum - --> $DIR/naked-with-invalid-repr-attr.rs:41:8 + --> $DIR/naked-with-invalid-repr-attr.rs:42:8 | LL | #[repr(u8)] | ^^ diff --git a/tests/ui/associated-inherent-types/bound_vars_in_args.rs b/tests/ui/associated-inherent-types/bound_vars_in_args.rs new file mode 100644 index 000000000000..49a9ef31cd67 --- /dev/null +++ b/tests/ui/associated-inherent-types/bound_vars_in_args.rs @@ -0,0 +1,22 @@ +#![feature(non_lifetime_binders, inherent_associated_types)] +#![expect(incomplete_features)] + +// Test whether we can resolve to the right IAT when the self type +// contains a bound type. This should ideally use the second impl. + +struct Foo(T); + +impl Foo<[u8]> { + type IAT = u8; +} + +impl Foo { + type IAT = u8; +} + +struct Bar +where + for Foo::IAT: Sized; + //~^ ERROR: multiple applicable items in scope + +fn main() {} diff --git a/tests/ui/associated-inherent-types/bound_vars_in_args.stderr b/tests/ui/associated-inherent-types/bound_vars_in_args.stderr new file mode 100644 index 000000000000..9e880476f6a9 --- /dev/null +++ b/tests/ui/associated-inherent-types/bound_vars_in_args.stderr @@ -0,0 +1,20 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/bound_vars_in_args.rs:19:20 + | +LL | for Foo::IAT: Sized; + | ^^^ multiple `IAT` found + | +note: candidate #1 is defined in an impl for the type `Foo<[u8]>` + --> $DIR/bound_vars_in_args.rs:10:5 + | +LL | type IAT = u8; + | ^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Foo` + --> $DIR/bound_vars_in_args.rs:14:5 + | +LL | type IAT = u8; + | ^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr deleted file mode 100644 index 7f8ed8985252..000000000000 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0391]: cycle detected when computing predicates of `Foo` - --> $DIR/cycle-iat-inside-of-adt.rs:7:1 - | -LL | struct Foo { - | ^^^^^^^^^^ - | -note: ...which requires computing inferred outlives-predicates of `Foo`... - --> $DIR/cycle-iat-inside-of-adt.rs:7:1 - | -LL | struct Foo { - | ^^^^^^^^^^ - = note: ...which requires computing the inferred outlives-predicates for items in this crate... -note: ...which requires computing type of `Foo::bar`... - --> $DIR/cycle-iat-inside-of-adt.rs:8:5 - | -LL | bar: Self::Bar, - | ^^^^^^^^^^^^^^ -note: ...which requires computing normalized predicates of `Foo`... - --> $DIR/cycle-iat-inside-of-adt.rs:7:1 - | -LL | struct Foo { - | ^^^^^^^^^^ - = note: ...which again requires computing predicates of `Foo`, completing the cycle -note: cycle used when checking that `Foo` is well-formed - --> $DIR/cycle-iat-inside-of-adt.rs:7:1 - | -LL | struct Foo { - | ^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.rs b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.rs deleted file mode 100644 index 902094b98628..000000000000 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: unknown - -#![feature(inherent_associated_types)] -#![allow(incomplete_features)] - -// FIXME(inherent_associated_types): This shouldn't lead to a cycle error. - -fn user() where S::P: std::fmt::Debug {} - -struct S; - -impl S { - type P = (); -} - -fn main() {} diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr deleted file mode 100644 index e97a5df9d491..000000000000 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error[E0391]: cycle detected when computing predicates of `user` - --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1 - | -LL | fn user() where S::P: std::fmt::Debug {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires computing explicit predicates of `user`... - --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1 - | -LL | fn user() where S::P: std::fmt::Debug {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires computing normalized predicates of `user`... - --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1 - | -LL | fn user() where S::P: std::fmt::Debug {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires computing predicates of `user`, completing the cycle -note: cycle used when checking that `user` is well-formed - --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1 - | -LL | fn user() where S::P: std::fmt::Debug {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error[E0392]: type parameter `T` is never used - --> $DIR/cycle-iat-inside-of-where-predicate.rs:10:10 - | -LL | struct S; - | ^ unused type parameter - | - = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0391, E0392. -For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-inherent-types/candidate-with-alias-2.rs b/tests/ui/associated-inherent-types/candidate-with-alias-2.rs new file mode 100644 index 000000000000..551d30a8786e --- /dev/null +++ b/tests/ui/associated-inherent-types/candidate-with-alias-2.rs @@ -0,0 +1,29 @@ +#![feature(inherent_associated_types)] +#![expect(incomplete_features)] + +// A behaviour test showcasing that we do not normalize associated types in +// the impl self ty when assembling IAT candidates + +trait Identity { + type Assoc; +} +impl Identity for T { + type Assoc = T; +} + +struct Foo(T); +impl Foo<::Assoc> { + type Inherent = u8; +} +impl Foo<::Assoc> { + type Inherent = u32; +} + +struct Bar { + field: >::Inherent, + //~^ ERROR: multiple applicable items in scope +} + +fn main() { + Bar { field: 10_u8 }; +} diff --git a/tests/ui/associated-inherent-types/candidate-with-alias-2.stderr b/tests/ui/associated-inherent-types/candidate-with-alias-2.stderr new file mode 100644 index 000000000000..2b79b65f22ba --- /dev/null +++ b/tests/ui/associated-inherent-types/candidate-with-alias-2.stderr @@ -0,0 +1,20 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/candidate-with-alias-2.rs:23:23 + | +LL | field: >::Inherent, + | ^^^^^^^^ multiple `Inherent` found + | +note: candidate #1 is defined in an impl for the type `Foo<::Assoc>` + --> $DIR/candidate-with-alias-2.rs:16:5 + | +LL | type Inherent = u8; + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Foo<::Assoc>` + --> $DIR/candidate-with-alias-2.rs:19:5 + | +LL | type Inherent = u32; + | ^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/associated-inherent-types/candidate-with-alias.rs b/tests/ui/associated-inherent-types/candidate-with-alias.rs new file mode 100644 index 000000000000..a84da195c26b --- /dev/null +++ b/tests/ui/associated-inherent-types/candidate-with-alias.rs @@ -0,0 +1,30 @@ +//@ check-pass + +#![feature(inherent_associated_types)] +#![expect(incomplete_features)] + +// A behaviour test showcasing that IAT resolution can pick the right +// candidate even if it has an alias, if it's the only candidate. + +trait Identity { + type Assoc; +} +impl Identity for T { + type Assoc = T; +} + +struct Foo(T); +impl Foo<::Assoc> { + type Inherent = u8; +} +impl Foo { + type Inherent = u32; +} + +struct Bar { + field: >::Inherent, +} + +fn main() { + Bar { field: 10_u8 }; +} diff --git a/tests/ui/associated-inherent-types/iat-in-where-bound.rs b/tests/ui/associated-inherent-types/iat-in-where-bound.rs new file mode 100644 index 000000000000..3b8b95eec9a4 --- /dev/null +++ b/tests/ui/associated-inherent-types/iat-in-where-bound.rs @@ -0,0 +1,14 @@ +//@ check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +fn user() where S::P: std::fmt::Debug {} + +struct S(T); + +impl S { + type P = (); +} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.rs b/tests/ui/associated-inherent-types/iat-inside-of-adt.rs similarity index 61% rename from tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.rs rename to tests/ui/associated-inherent-types/iat-inside-of-adt.rs index 64168cb8c14f..3d88016d0f87 100644 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.rs +++ b/tests/ui/associated-inherent-types/iat-inside-of-adt.rs @@ -1,8 +1,7 @@ -//@ known-bug: #108491 +//@ check-pass #![feature(inherent_associated_types)] #![allow(incomplete_features)] -// FIXME(inherent_associated_types): This should pass. struct Foo { bar: Self::Bar, @@ -11,4 +10,8 @@ impl Foo { pub type Bar = usize; } -fn main() {} +fn main() { + Foo { + bar: 10_usize, + }; +} diff --git a/tests/ui/associated-inherent-types/impl_params_are_infers.rs b/tests/ui/associated-inherent-types/impl_params_are_infers.rs new file mode 100644 index 000000000000..55d29a35a231 --- /dev/null +++ b/tests/ui/associated-inherent-types/impl_params_are_infers.rs @@ -0,0 +1,34 @@ +#![feature(inherent_associated_types)] +#![expect(incomplete_features)] + +// Test whether IAT resolution in item signatures will actually instantiate the +// impl's params with infers before equating self types, or if we "cheat" and +// use a heuristic (e.g. DeepRejectCtxt). + +struct Foo(T, U, V); + +impl Foo { + type IAT = u8; +} + +impl Foo { + type IAT = u16; +} + +trait Identity { + type This; +} +impl Identity for T { + type This = T; +} + +struct Bar { + // It would be illegal to resolve to `Foo::IAT` as `T` and `U` are + // different types. However, currently we treat all impl-side params sort of like + // they're infers and assume they can unify with anything, so we consider it a + // valid candidate. + field: Foo::This>::IAT, + //~^ ERROR: multiple applicable items in scope +} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/impl_params_are_infers.stderr b/tests/ui/associated-inherent-types/impl_params_are_infers.stderr new file mode 100644 index 000000000000..fd31693cbedc --- /dev/null +++ b/tests/ui/associated-inherent-types/impl_params_are_infers.stderr @@ -0,0 +1,20 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/impl_params_are_infers.rs:30:48 + | +LL | field: Foo::This>::IAT, + | ^^^ multiple `IAT` found + | +note: candidate #1 is defined in an impl for the type `Foo` + --> $DIR/impl_params_are_infers.rs:11:5 + | +LL | type IAT = u8; + | ^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Foo` + --> $DIR/impl_params_are_infers.rs:15:5 + | +LL | type IAT = u16; + | ^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/crashes/125879.rs b/tests/ui/associated-inherent-types/inhabited-predicates.rs similarity index 50% rename from tests/crashes/125879.rs rename to tests/ui/associated-inherent-types/inhabited-predicates.rs index 4318842e4551..2b041d4e1be2 100644 --- a/tests/crashes/125879.rs +++ b/tests/ui/associated-inherent-types/inhabited-predicates.rs @@ -1,8 +1,10 @@ -//@ known-bug: rust-lang/rust#125879 +//@ check-pass + #![feature(inherent_associated_types)] -#![allow(incomplete_features)] +#![expect(incomplete_features)] pub type PubAlias0 = PubTy::PrivAssocTy; +//~^ WARN: associated type `PubTy::PrivAssocTy` is more private than the item `PubAlias0` pub struct PubTy; impl PubTy { @@ -10,6 +12,7 @@ impl PubTy { } pub struct S(pub PubAlias0); +//~^ WARN: associated type `PubTy::PrivAssocTy` is more private than the item `S::0` pub unsafe fn foo(a: S) -> S { a diff --git a/tests/ui/associated-inherent-types/inhabited-predicates.stderr b/tests/ui/associated-inherent-types/inhabited-predicates.stderr new file mode 100644 index 000000000000..e43cd034e675 --- /dev/null +++ b/tests/ui/associated-inherent-types/inhabited-predicates.stderr @@ -0,0 +1,27 @@ +warning: associated type `PubTy::PrivAssocTy` is more private than the item `PubAlias0` + --> $DIR/inhabited-predicates.rs:6:1 + | +LL | pub type PubAlias0 = PubTy::PrivAssocTy; + | ^^^^^^^^^^^^^^^^^^ type alias `PubAlias0` is reachable at visibility `pub` + | +note: but associated type `PubTy::PrivAssocTy` is only usable at visibility `pub(crate)` + --> $DIR/inhabited-predicates.rs:11:5 + | +LL | type PrivAssocTy = (); + | ^^^^^^^^^^^^^^^^ + = note: `#[warn(private_interfaces)]` on by default + +warning: associated type `PubTy::PrivAssocTy` is more private than the item `S::0` + --> $DIR/inhabited-predicates.rs:14:14 + | +LL | pub struct S(pub PubAlias0); + | ^^^^^^^^^^^^^ field `S::0` is reachable at visibility `pub` + | +note: but associated type `PubTy::PrivAssocTy` is only usable at visibility `pub(crate)` + --> $DIR/inhabited-predicates.rs:11:5 + | +LL | type PrivAssocTy = (); + | ^^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/associated-inherent-types/issue-109299-1.rs b/tests/ui/associated-inherent-types/issue-109299-1.rs index 4546785f0b1c..3132d9fef697 100644 --- a/tests/ui/associated-inherent-types/issue-109299-1.rs +++ b/tests/ui/associated-inherent-types/issue-109299-1.rs @@ -8,8 +8,6 @@ impl Lexer { } type X = impl for Fn() -> Lexer::Cursor; -//~^ ERROR associated type `Cursor` not found for `Lexer` in the current scope -//~| ERROR associated type `Cursor` not found for `Lexer` in the current scope -//~| ERROR: unconstrained opaque type +//~^ ERROR: unconstrained opaque type fn main() {} diff --git a/tests/ui/associated-inherent-types/issue-109299-1.stderr b/tests/ui/associated-inherent-types/issue-109299-1.stderr index 6bc7a539680c..bc8ea6acf28c 100644 --- a/tests/ui/associated-inherent-types/issue-109299-1.stderr +++ b/tests/ui/associated-inherent-types/issue-109299-1.stderr @@ -6,31 +6,5 @@ LL | type X = impl for Fn() -> Lexer::Cursor; | = note: `X` must be used in combination with a concrete type within the same crate -error[E0220]: associated type `Cursor` not found for `Lexer` in the current scope - --> $DIR/issue-109299-1.rs:10:40 - | -LL | struct Lexer(T); - | --------------- associated type `Cursor` not found for this struct -... -LL | type X = impl for Fn() -> Lexer::Cursor; - | ^^^^^^ associated item not found in `Lexer` - | - = note: the associated type was found for - - `Lexer` +error: aborting due to 1 previous error -error[E0220]: associated type `Cursor` not found for `Lexer` in the current scope - --> $DIR/issue-109299-1.rs:10:40 - | -LL | struct Lexer(T); - | --------------- associated type `Cursor` not found for this struct -... -LL | type X = impl for Fn() -> Lexer::Cursor; - | ^^^^^^ associated item not found in `Lexer` - | - = note: the associated type was found for - - `Lexer` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-inherent-types/multiple-candidates-in-adt-field-1.rs b/tests/ui/associated-inherent-types/multiple-candidates-in-adt-field-1.rs new file mode 100644 index 000000000000..7723ee9c58d9 --- /dev/null +++ b/tests/ui/associated-inherent-types/multiple-candidates-in-adt-field-1.rs @@ -0,0 +1,23 @@ +//@ check-pass + +#![feature(inherent_associated_types)] +#![expect(incomplete_features)] + +// Test that when resolving an IAT we select candidates based +// off whether the self type matches not just the name of the IAT + +struct Foo(T); +impl Foo { + type Inherent = u8; +} +impl Foo { + type Inherent = u32; +} + +struct Bar { + field: >::Inherent, +} + +fn main() { + Bar { field: 10_u32 }; +} diff --git a/tests/ui/associated-inherent-types/multiple-candidates-in-adt-field-2.rs b/tests/ui/associated-inherent-types/multiple-candidates-in-adt-field-2.rs new file mode 100644 index 000000000000..8a6d1896f7d2 --- /dev/null +++ b/tests/ui/associated-inherent-types/multiple-candidates-in-adt-field-2.rs @@ -0,0 +1,29 @@ +#![feature(inherent_associated_types)] +#![expect(incomplete_features)] + +// Test that when we have an unnormalized projection in the IAT self ty +// we don't normalize it to determine which IAT to resolve to. + +struct Foo(T); +impl Foo { + type Inherent = u16; +} +impl Foo { + type Inherent = u32; +} + +struct Bar { + field: ::This>>::Inherent, + //~^ ERROR: multiple applicable items in scope +} + +trait Identity { + type This; +} +impl Identity for T { type This = T; } + +fn main() { + Bar { + field: 1_u16, + }; +} diff --git a/tests/ui/associated-inherent-types/multiple-candidates-in-adt-field-2.stderr b/tests/ui/associated-inherent-types/multiple-candidates-in-adt-field-2.stderr new file mode 100644 index 000000000000..df8c124f77fa --- /dev/null +++ b/tests/ui/associated-inherent-types/multiple-candidates-in-adt-field-2.stderr @@ -0,0 +1,20 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/multiple-candidates-in-adt-field-2.rs:16:43 + | +LL | field: ::This>>::Inherent, + | ^^^^^^^^ multiple `Inherent` found + | +note: candidate #1 is defined in an impl for the type `Foo` + --> $DIR/multiple-candidates-in-adt-field-2.rs:9:5 + | +LL | type Inherent = u16; + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Foo` + --> $DIR/multiple-candidates-in-adt-field-2.rs:12:5 + | +LL | type Inherent = u32; + | ^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/associated-inherent-types/multiple-candidates-in-adt-field-3.rs b/tests/ui/associated-inherent-types/multiple-candidates-in-adt-field-3.rs new file mode 100644 index 000000000000..4c5b382463d5 --- /dev/null +++ b/tests/ui/associated-inherent-types/multiple-candidates-in-adt-field-3.rs @@ -0,0 +1,27 @@ +//@ check-pass + +#![feature(inherent_associated_types, lazy_type_alias)] +#![expect(incomplete_features)] + +// Test that we *do* normalize free aliases in order to resolve +// between multiple IAT candidates + +type Free = u8; + +struct Foo(T); +impl Foo { + type Assoc = u16; +} +impl Foo { + type Assoc = u32; +} + +struct Bar { + field: >::Assoc, +} + +fn main() { + Bar { + field: 1_u16, + }; +} diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.rs b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.rs index c205cb800d2f..337fd8fa00c5 100644 --- a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.rs +++ b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.rs @@ -27,5 +27,5 @@ impl S<()> { fn main() { let _: S::::Pr = (); //[shadowed]~^ ERROR associated type `Pr` not found - //[uncovered]~^^ ERROR ambiguous associated type + //[uncovered]~^^ ERROR associated type `Pr` not found } diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr index 3e914e0538d0..f35158c5b410 100644 --- a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr +++ b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr @@ -1,15 +1,15 @@ -error[E0223]: ambiguous associated type - --> $DIR/not-found-self-type-differs-shadowing-trait-item.rs:28:12 +error[E0220]: associated type `Pr` not found for `S` in the current scope + --> $DIR/not-found-self-type-differs-shadowing-trait-item.rs:28:23 | +LL | struct S(T); + | ----------- associated type `Pr` not found for this struct +... LL | let _: S::::Pr = (); - | ^^^^^^^^^^^^^ - | -help: use fully-qualified syntax - | -LL - let _: S::::Pr = (); -LL + let _: as Tr>::Pr = (); + | ^^ associated item not found in `S` | + = note: the associated type was found for + error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0223`. +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-inherent-types/really_deep_self_ty_mismatch.rs b/tests/ui/associated-inherent-types/really_deep_self_ty_mismatch.rs new file mode 100644 index 000000000000..eac33f631bbc --- /dev/null +++ b/tests/ui/associated-inherent-types/really_deep_self_ty_mismatch.rs @@ -0,0 +1,26 @@ +//@ check-pass + +#![feature(inherent_associated_types)] +#![expect(incomplete_features)] + +// Test that IAT resolution doesn't bail out when the self type is +// very nested. + +struct Foo(T); +#[rustfmt::skip] +impl Foo>>>>>>>>>> { + type Inherent = u16; +} +#[rustfmt::skip] +impl Foo>>>>>>>>>> { + type Inherent = u32; +} + +#[rustfmt::skip] +struct Bar { + field: >>>>>>>>>>>::Inherent, +} + +fn main() { + Bar { field: 1_u16 }; +} diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr index 8b6f0a47aed9..b17e26b608d9 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr @@ -2,9 +2,8 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-1.rs:24:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ `Self` cannot be formatted with the default formatter + | ^^^^ the trait `std::fmt::Display` is not implemented for `Self` | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `UncheckedCopy::Output` --> $DIR/defaults-unsound-62211-1.rs:24:86 | diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr index 010f51df15ad..a858c9c1ba04 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr @@ -2,9 +2,8 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-1.rs:24:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ `Self` cannot be formatted with the default formatter + | ^^^^ the trait `std::fmt::Display` is not implemented for `Self` | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `UncheckedCopy::Output` --> $DIR/defaults-unsound-62211-1.rs:24:86 | diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr index 7552b0891333..facfec85afe3 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr @@ -2,9 +2,8 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-2.rs:24:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ `Self` cannot be formatted with the default formatter + | ^^^^ the trait `std::fmt::Display` is not implemented for `Self` | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `UncheckedCopy::Output` --> $DIR/defaults-unsound-62211-2.rs:24:86 | diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr index 934789465707..1360843172f9 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr @@ -2,9 +2,8 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-2.rs:24:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - | ^^^^ `Self` cannot be formatted with the default formatter + | ^^^^ the trait `std::fmt::Display` is not implemented for `Self` | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `UncheckedCopy::Output` --> $DIR/defaults-unsound-62211-2.rs:24:86 | diff --git a/tests/ui/async-await/async-drop/async-without-sync.rs b/tests/ui/async-await/async-drop/async-without-sync.rs new file mode 100644 index 000000000000..8a748636cc78 --- /dev/null +++ b/tests/ui/async-await/async-drop/async-without-sync.rs @@ -0,0 +1,19 @@ +//@ edition: 2024 +#![feature(async_drop)] +#![allow(incomplete_features)] +#![crate_type = "lib"] + +use std::future::AsyncDrop; +use std::pin::Pin; + +async fn foo() { + let _st = St; +} + +struct St; + +impl AsyncDrop for St { //~ ERROR: `AsyncDrop` impl without `Drop` impl + async fn drop(self: Pin<&mut Self>) { + println!("123"); + } +} diff --git a/tests/ui/async-await/async-drop/async-without-sync.stderr b/tests/ui/async-await/async-drop/async-without-sync.stderr new file mode 100644 index 000000000000..0eaca322dc03 --- /dev/null +++ b/tests/ui/async-await/async-drop/async-without-sync.stderr @@ -0,0 +1,10 @@ +error: `AsyncDrop` impl without `Drop` impl + --> $DIR/async-without-sync.rs:15:1 + | +LL | impl AsyncDrop for St { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: type implementing `AsyncDrop` trait must also implement `Drop` trait to be used in sync context and unwinds + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed b/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed index c74a32e442f3..9e5e889506c7 100644 --- a/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed +++ b/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed @@ -4,5 +4,5 @@ // Regression test for issue 79694 fn main() { - let _ = async move { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect + let _ = async move { }; //~ ERROR the order of `move` and `async` is incorrect } diff --git a/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs b/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs index 81ffbacc3273..9c36a6c96da6 100644 --- a/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs +++ b/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs @@ -4,5 +4,5 @@ // Regression test for issue 79694 fn main() { - let _ = move async { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect + let _ = move async { }; //~ ERROR the order of `move` and `async` is incorrect } diff --git a/tests/ui/attributes/arg-error-issue-121425.stderr b/tests/ui/attributes/arg-error-issue-121425.stderr index 6e71f15fdc87..1beb99b1703c 100644 --- a/tests/ui/attributes/arg-error-issue-121425.stderr +++ b/tests/ui/attributes/arg-error-issue-121425.stderr @@ -1,9 +1,3 @@ -error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses - --> $DIR/arg-error-issue-121425.rs:16:8 - | -LL | #[repr(align())] - | ^^^^^^^ - error[E0693]: incorrect `repr(align)` attribute format: `align` expects a literal integer as argument --> $DIR/arg-error-issue-121425.rs:4:14 | @@ -22,6 +16,12 @@ error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer LL | #[repr(align("str"))] | ^^^^^ +error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses + --> $DIR/arg-error-issue-121425.rs:16:8 + | +LL | #[repr(align())] + | ^^^^^^^ + error[E0552]: incorrect `repr(packed)` attribute format: `packed` expects a literal integer as argument --> $DIR/arg-error-issue-121425.rs:21:15 | diff --git a/tests/ui/attributes/expected-word.rs b/tests/ui/attributes/expected-word.rs new file mode 100644 index 000000000000..246aa78db828 --- /dev/null +++ b/tests/ui/attributes/expected-word.rs @@ -0,0 +1,3 @@ +#[cold = true] +//~^ ERROR malformed `cold` attribute input [E0565] +fn main() {} diff --git a/tests/ui/attributes/expected-word.stderr b/tests/ui/attributes/expected-word.stderr new file mode 100644 index 000000000000..dcb10e7aee89 --- /dev/null +++ b/tests/ui/attributes/expected-word.stderr @@ -0,0 +1,12 @@ +error[E0565]: malformed `cold` attribute input + --> $DIR/expected-word.rs:1:1 + | +LL | #[cold = true] + | ^^^^^^^------^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[cold]` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/attributes/invalid-repr.rs b/tests/ui/attributes/invalid-repr.rs index 10a487c127ec..d7933533405c 100644 --- a/tests/ui/attributes/invalid-repr.rs +++ b/tests/ui/attributes/invalid-repr.rs @@ -1,5 +1,5 @@ #[repr(align(16))] -//~^ ERROR attribute should be applied to a struct, enum, function, associated function, or union +//~^ ERROR attribute should be applied to a struct, enum, or union pub type Foo = i32; fn main() {} diff --git a/tests/ui/attributes/invalid-repr.stderr b/tests/ui/attributes/invalid-repr.stderr index 681460ad0812..3f5a305c6b70 100644 --- a/tests/ui/attributes/invalid-repr.stderr +++ b/tests/ui/attributes/invalid-repr.stderr @@ -1,11 +1,11 @@ -error[E0517]: attribute should be applied to a struct, enum, function, associated function, or union +error[E0517]: attribute should be applied to a struct, enum, or union --> $DIR/invalid-repr.rs:1:8 | LL | #[repr(align(16))] | ^^^^^^^^^ LL | LL | pub type Foo = i32; - | ------------------- not a struct, enum, function, associated function, or union + | ------------------- not a struct, enum, or union error: aborting due to 1 previous error diff --git a/tests/ui/attributes/lint_on_root.rs b/tests/ui/attributes/lint_on_root.rs new file mode 100644 index 000000000000..93d47bf0d714 --- /dev/null +++ b/tests/ui/attributes/lint_on_root.rs @@ -0,0 +1,7 @@ +// NOTE: this used to panic in debug builds (by a sanity assertion) +// and not emit any lint on release builds. See https://github.com/rust-lang/rust/issues/142891. +#![inline = ""] +//~^ ERROR valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` +//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +fn main() {} diff --git a/tests/ui/attributes/lint_on_root.stderr b/tests/ui/attributes/lint_on_root.stderr new file mode 100644 index 000000000000..aaa46e6f54ba --- /dev/null +++ b/tests/ui/attributes/lint_on_root.stderr @@ -0,0 +1,12 @@ +error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` + --> $DIR/lint_on_root.rs:3:1 + | +LL | #![inline = ""] + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + = note: `#[deny(ill_formed_attribute_input)]` on by default + +error: aborting due to 1 previous error + diff --git a/tests/ui/attributes/malformed-fn-align.rs b/tests/ui/attributes/malformed-fn-align.rs index 4aaad01b7235..f5ab9555e561 100644 --- a/tests/ui/attributes/malformed-fn-align.rs +++ b/tests/ui/attributes/malformed-fn-align.rs @@ -2,6 +2,24 @@ #![crate_type = "lib"] trait MyTrait { - #[repr(align)] //~ ERROR invalid `repr(align)` attribute: `align` needs an argument - fn myfun(); + #[align] //~ ERROR malformed `align` attribute input + fn myfun1(); + + #[align(1, 2)] //~ ERROR malformed `align` attribute input + fn myfun2(); } + +#[align = 16] //~ ERROR malformed `align` attribute input +fn f1() {} + +#[align("hello")] //~ ERROR invalid alignment value: not an unsuffixed integer +fn f2() {} + +#[align(0)] //~ ERROR invalid alignment value: not a power of two +fn f3() {} + +#[repr(align(16))] //~ ERROR `#[repr(align(...))]` is not supported on function items +fn f4() {} + +#[align(16)] //~ ERROR `#[align(...)]` is not supported on struct items +struct S1; diff --git a/tests/ui/attributes/malformed-fn-align.stderr b/tests/ui/attributes/malformed-fn-align.stderr index 57913c48ef78..b769d0b457dd 100644 --- a/tests/ui/attributes/malformed-fn-align.stderr +++ b/tests/ui/attributes/malformed-fn-align.stderr @@ -1,9 +1,67 @@ -error[E0589]: invalid `repr(align)` attribute: `align` needs an argument - --> $DIR/malformed-fn-align.rs:5:12 +error[E0539]: malformed `align` attribute input + --> $DIR/malformed-fn-align.rs:5:5 | -LL | #[repr(align)] - | ^^^^^ help: supply an argument here: `align(...)` +LL | #[align] + | ^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[align()]` -error: aborting due to 1 previous error +error[E0805]: malformed `align` attribute input + --> $DIR/malformed-fn-align.rs:8:5 + | +LL | #[align(1, 2)] + | ^^^^^^^------^ + | | | + | | expected a single argument here + | help: must be of the form: `#[align()]` -For more information about this error, try `rustc --explain E0589`. +error[E0539]: malformed `align` attribute input + --> $DIR/malformed-fn-align.rs:12:1 + | +LL | #[align = 16] + | ^^^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[align()]` + +error[E0589]: invalid alignment value: not an unsuffixed integer + --> $DIR/malformed-fn-align.rs:15:9 + | +LL | #[align("hello")] + | ^^^^^^^ + +error[E0589]: invalid alignment value: not a power of two + --> $DIR/malformed-fn-align.rs:18:9 + | +LL | #[align(0)] + | ^ + +error: `#[repr(align(...))]` is not supported on function items + --> $DIR/malformed-fn-align.rs:21:8 + | +LL | #[repr(align(16))] + | ^^^^^^^^^ + | +help: use `#[align(...)]` instead + --> $DIR/malformed-fn-align.rs:21:8 + | +LL | #[repr(align(16))] + | ^^^^^^^^^ + +error: `#[align(...)]` is not supported on struct items + --> $DIR/malformed-fn-align.rs:24:1 + | +LL | #[align(16)] + | ^^^^^^^^^^^^ + | +help: use `#[repr(align(...))]` instead + | +LL - #[align(16)] +LL + #[repr(align(16))] + | + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0539, E0589, E0805. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/attributes/malformed-must_use.rs b/tests/ui/attributes/malformed-must_use.rs new file mode 100644 index 000000000000..4b98affa8abd --- /dev/null +++ b/tests/ui/attributes/malformed-must_use.rs @@ -0,0 +1,4 @@ +#[must_use()] //~ ERROR valid forms for the attribute are `#[must_use = "reason"]` and `#[must_use]` +struct Test; + +fn main() {} diff --git a/tests/ui/attributes/malformed-must_use.stderr b/tests/ui/attributes/malformed-must_use.stderr new file mode 100644 index 000000000000..c948ba677444 --- /dev/null +++ b/tests/ui/attributes/malformed-must_use.stderr @@ -0,0 +1,8 @@ +error: valid forms for the attribute are `#[must_use = "reason"]` and `#[must_use]` + --> $DIR/malformed-must_use.rs:1:1 + | +LL | #[must_use()] + | ^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/attributes/rustc_skip_during_method_dispatch.rs b/tests/ui/attributes/rustc_skip_during_method_dispatch.rs new file mode 100644 index 000000000000..25b473d5a585 --- /dev/null +++ b/tests/ui/attributes/rustc_skip_during_method_dispatch.rs @@ -0,0 +1,38 @@ +#![feature(rustc_attrs)] + +#[rustc_skip_during_method_dispatch] +//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input [E0539] +trait NotAList {} + +#[rustc_skip_during_method_dispatch = "array"] +//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input [E0539] +trait AlsoNotAList {} + +#[rustc_skip_during_method_dispatch()] +//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input +trait Argless {} + +#[rustc_skip_during_method_dispatch(array, boxed_slice, array)] +//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input +trait Duplicate {} + +#[rustc_skip_during_method_dispatch(slice)] +//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input +trait Unexpected {} + +#[rustc_skip_during_method_dispatch(array = true)] +//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input +trait KeyValue {} + +#[rustc_skip_during_method_dispatch("array")] +//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input +trait String {} + +#[rustc_skip_during_method_dispatch(array, boxed_slice)] +trait OK {} + +#[rustc_skip_during_method_dispatch(array)] +//~^ ERROR: attribute should be applied to a trait +impl OK for () {} + +fn main() {} diff --git a/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr b/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr new file mode 100644 index 000000000000..2f5d79684899 --- /dev/null +++ b/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr @@ -0,0 +1,76 @@ +error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input + --> $DIR/rustc_skip_during_method_dispatch.rs:3:1 + | +LL | #[rustc_skip_during_method_dispatch] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]` + +error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input + --> $DIR/rustc_skip_during_method_dispatch.rs:7:1 + | +LL | #[rustc_skip_during_method_dispatch = "array"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]` + +error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input + --> $DIR/rustc_skip_during_method_dispatch.rs:11:1 + | +LL | #[rustc_skip_during_method_dispatch()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--^ + | | | + | | expected at least 1 argument here + | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]` + +error[E0538]: malformed `rustc_skip_during_method_dispatch` attribute input + --> $DIR/rustc_skip_during_method_dispatch.rs:15:1 + | +LL | #[rustc_skip_during_method_dispatch(array, boxed_slice, array)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----^^ + | | | + | | found `array` used as a key more than once + | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]` + +error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input + --> $DIR/rustc_skip_during_method_dispatch.rs:19:1 + | +LL | #[rustc_skip_during_method_dispatch(slice)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----^^ + | | | + | | valid arguments are `array` or `boxed_slice` + | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]` + +error[E0565]: malformed `rustc_skip_during_method_dispatch` attribute input + --> $DIR/rustc_skip_during_method_dispatch.rs:23:1 + | +LL | #[rustc_skip_during_method_dispatch(array = true)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]` + +error[E0565]: malformed `rustc_skip_during_method_dispatch` attribute input + --> $DIR/rustc_skip_during_method_dispatch.rs:27:1 + | +LL | #[rustc_skip_during_method_dispatch("array")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^ + | | | + | | didn't expect a literal here + | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]` + +error: attribute should be applied to a trait + --> $DIR/rustc_skip_during_method_dispatch.rs:34:1 + | +LL | #[rustc_skip_during_method_dispatch(array)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | impl OK for () {} + | ----------------- not a trait + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0538, E0539, E0565. +For more information about an error, try `rustc --explain E0538`. diff --git a/tests/ui/binop/issue-77910-1.stderr b/tests/ui/binop/issue-77910-1.stderr index 74deac900d42..80c384f39bd1 100644 --- a/tests/ui/binop/issue-77910-1.stderr +++ b/tests/ui/binop/issue-77910-1.stderr @@ -16,9 +16,8 @@ LL | fn foo(s: &i32) -> &i32 { | --- consider calling this function ... LL | assert_eq!(foo, y); - | ^^^^^^^^^^^^^^^^^^ `for<'a> fn(&'a i32) -> &'a i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for fn item `for<'a> fn(&'a i32) -> &'a i32 {foo}` | - = help: the trait `Debug` is not implemented for fn item `for<'a> fn(&'a i32) -> &'a i32 {foo}` = help: use parentheses to call this function: `foo(/* &i32 */)` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr index 911c136086cf..72580e7464b7 100644 --- a/tests/ui/borrowck/clone-on-ref.stderr +++ b/tests/ui/borrowck/clone-on-ref.stderr @@ -30,7 +30,7 @@ LL | drop(x); | ^ move out of `x` occurs here LL | LL | println!("{b}"); - | --- borrow later used here + | - borrow later used here | help: if `T` implemented `Clone`, you could clone the value --> $DIR/clone-on-ref.rs:11:8 @@ -57,7 +57,7 @@ LL | drop(x); | ^ move out of `x` occurs here LL | LL | println!("{b:?}"); - | ----- borrow later used here + | - borrow later used here | note: if `A` implemented `Clone`, you could clone the value --> $DIR/clone-on-ref.rs:19:1 diff --git a/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.rs b/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.rs deleted file mode 100644 index 4a6c2f9ed065..000000000000 --- a/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![allow(dead_code)] - -fn bar<'a>(_: std::fmt::Arguments<'a>) {} -fn main() { - let x = format_args!("a {} {} {}.", 1, format_args!("b{}!", 2), 3); - //~^ ERROR temporary value dropped while borrowed - - bar(x); - - let foo = format_args!("{}", "hi"); - //~^ ERROR temporary value dropped while borrowed - bar(foo); - - let foo = format_args!("hi"); // no placeholder in arguments, so no error - bar(foo); -} diff --git a/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr b/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr deleted file mode 100644 index 30f292f71a28..000000000000 --- a/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0716]: temporary value dropped while borrowed - --> $DIR/issue-114374-invalid-help-fmt-args.rs:5:13 - | -LL | let x = format_args!("a {} {} {}.", 1, format_args!("b{}!", 2), 3); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement - | | - | creates a temporary value which is freed while still in use -... -LL | bar(x); - | - borrow later used here - | - = note: the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used - = note: to learn more, visit - -error[E0716]: temporary value dropped while borrowed - --> $DIR/issue-114374-invalid-help-fmt-args.rs:10:15 - | -LL | let foo = format_args!("{}", "hi"); - | ^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement - | | - | creates a temporary value which is freed while still in use -LL | -LL | bar(foo); - | --- borrow later used here - | - = note: the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used - = note: to learn more, visit - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index f29a41d6a8e2..f422919983b7 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -211,10 +211,6 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `reference-types` `relax` `relaxed-simd` -`reserve-x18` -`retpoline-external-thunk` -`retpoline-indirect-branches` -`retpoline-indirect-calls` `rtm` `sb` `scq` diff --git a/tests/ui/closures/issue-111932.stderr b/tests/ui/closures/issue-111932.stderr index 93488ad2011e..fc3b7b0c6e66 100644 --- a/tests/ui/closures/issue-111932.stderr +++ b/tests/ui/closures/issue-111932.stderr @@ -14,11 +14,9 @@ error[E0277]: the size for values of type `dyn Foo` cannot be known at compilati LL | println!("{:?}", foo); | ---- ^^^ doesn't have a size known at compile-time | | - | required by a bound introduced by this call + | required by this formatting parameter | = help: the trait `Sized` is not implemented for `dyn Foo` -note: required by an implicit `Sized` bound in `core::fmt::rt::Argument::<'_>::new_debug` - --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs index b25a81b858be..796c2634b623 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs @@ -2,15 +2,15 @@ //@ build-pass //@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib //@ needs-llvm-components: arm -#![feature(abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items, intrinsics)] +#![feature(abi_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items, intrinsics)] #![no_core] extern crate minicore; use minicore::*; #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn test( - f: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u32, +pub extern "cmse-nonsecure-entry" fn test( + f: extern "cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u32, a: u32, b: u32, c: u32, diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs index 2d0ed5d2a307..cb805309a02d 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs @@ -1,9 +1,9 @@ -// gate-test-abi_c_cmse_nonsecure_call -#[allow(unsupported_fn_ptr_calling_conventions)] +// gate-test-abi_cmse_nonsecure_call fn main() { let non_secure_function = unsafe { - core::mem::transmute:: i32>( - //~^ ERROR [E0658] + core::mem::transmute:: i32>( + //~^ ERROR: is not a supported ABI for the current target [E0570] + //~| ERROR: ABI is experimental and subject to change [E0658] 0x10000004, ) }; diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr index beb0ab70cc7e..ecf70e890f4c 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr @@ -1,23 +1,20 @@ -error[E0658]: the extern "C-cmse-nonsecure-call" ABI is experimental and subject to change - --> $DIR/gate_test.rs:5:46 +error[E0570]: "cmse-nonsecure-call" is not a supported ABI for the current target + --> $DIR/gate_test.rs:4:46 | -LL | core::mem::transmute:: i32>( - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | core::mem::transmute:: i32>( + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0658]: the extern "cmse-nonsecure-call" ABI is experimental and subject to change + --> $DIR/gate_test.rs:4:46 + | +LL | core::mem::transmute:: i32>( + | ^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #81391 for more information - = help: add `#![feature(abi_c_cmse_nonsecure_call)]` to the crate attributes to enable + = help: add `#![feature(abi_cmse_nonsecure_call)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. -Future incompatibility report: Future breakage diagnostic: -warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target - --> $DIR/gate_test.rs:5:39 - | -LL | core::mem::transmute:: i32>( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 +error: aborting due to 2 previous errors +Some errors have detailed explanations: E0570, E0658. +For more information about an error, try `rustc --explain E0570`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs index 84080890e080..4ce5890a2da3 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs @@ -1,7 +1,7 @@ //@ add-core-stubs //@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib //@ needs-llvm-components: arm -#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items)] +#![feature(abi_cmse_nonsecure_call, no_core, lang_items)] #![no_core] extern crate minicore; @@ -11,31 +11,31 @@ use minicore::*; struct Wrapper(T); struct Test { - f1: extern "C-cmse-nonsecure-call" fn(U, u32, u32, u32) -> u64, + f1: extern "cmse-nonsecure-call" fn(U, u32, u32, u32) -> u64, //~^ ERROR cannot find type `U` in this scope //~| ERROR function pointer types may not have generic parameters - f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64, + f2: extern "cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64, //~^ ERROR `impl Trait` is not allowed in `fn` pointer parameters - f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, //~ ERROR [E0798] - f4: extern "C-cmse-nonsecure-call" fn(Wrapper, u32, u32, u32) -> u64, //~ ERROR [E0798] + f3: extern "cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, //~ ERROR [E0798] + f4: extern "cmse-nonsecure-call" fn(Wrapper, u32, u32, u32) -> u64, //~ ERROR [E0798] } -type WithReference = extern "C-cmse-nonsecure-call" fn(&usize); +type WithReference = extern "cmse-nonsecure-call" fn(&usize); trait Trait {} -type WithTraitObject = extern "C-cmse-nonsecure-call" fn(&dyn Trait) -> &dyn Trait; -//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798] +type WithTraitObject = extern "cmse-nonsecure-call" fn(&dyn Trait) -> &dyn Trait; +//~^ ERROR return value of `"cmse-nonsecure-call"` function too large to pass via registers [E0798] type WithStaticTraitObject = - extern "C-cmse-nonsecure-call" fn(&'static dyn Trait) -> &'static dyn Trait; -//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798] + extern "cmse-nonsecure-call" fn(&'static dyn Trait) -> &'static dyn Trait; +//~^ ERROR return value of `"cmse-nonsecure-call"` function too large to pass via registers [E0798] #[repr(transparent)] struct WrapperTransparent<'a>(&'a dyn Trait); type WithTransparentTraitObject = - extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTransparent; -//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798] + extern "cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTransparent; +//~^ ERROR return value of `"cmse-nonsecure-call"` function too large to pass via registers [E0798] -type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...); -//~^ ERROR C-variadic functions with the "C-cmse-nonsecure-call" calling convention are not supported +type WithVarArgs = extern "cmse-nonsecure-call" fn(u32, ...); +//~^ ERROR C-variadic functions with the "cmse-nonsecure-call" calling convention are not supported diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr index 2b51f48915b3..156568535763 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr @@ -1,21 +1,21 @@ error: function pointer types may not have generic parameters - --> $DIR/generics.rs:14:42 + --> $DIR/generics.rs:14:40 | -LL | f1: extern "C-cmse-nonsecure-call" fn(U, u32, u32, u32) -> u64, - | ^^^^^^^^^ +LL | f1: extern "cmse-nonsecure-call" fn(U, u32, u32, u32) -> u64, + | ^^^^^^^^^ error[E0412]: cannot find type `U` in this scope - --> $DIR/generics.rs:14:52 + --> $DIR/generics.rs:14:50 | LL | struct Test { | - similarly named type parameter `T` defined here -LL | f1: extern "C-cmse-nonsecure-call" fn(U, u32, u32, u32) -> u64, - | ^ +LL | f1: extern "cmse-nonsecure-call" fn(U, u32, u32, u32) -> u64, + | ^ | help: a type parameter with a similar name exists | -LL - f1: extern "C-cmse-nonsecure-call" fn(U, u32, u32, u32) -> u64, -LL + f1: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, +LL - f1: extern "cmse-nonsecure-call" fn(U, u32, u32, u32) -> u64, +LL + f1: extern "cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, | help: you might be missing a type parameter | @@ -23,57 +23,57 @@ LL | struct Test { | +++ error[E0562]: `impl Trait` is not allowed in `fn` pointer parameters - --> $DIR/generics.rs:17:43 + --> $DIR/generics.rs:17:41 | -LL | f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64, - | ^^^^^^^^^ +LL | f2: extern "cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64, + | ^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type +error[E0798]: function pointers with the `"cmse-nonsecure-call"` ABI cannot contain generics in their type --> $DIR/generics.rs:19:9 | -LL | f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | f3: extern "cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type +error[E0798]: function pointers with the `"cmse-nonsecure-call"` ABI cannot contain generics in their type --> $DIR/generics.rs:20:9 | -LL | f4: extern "C-cmse-nonsecure-call" fn(Wrapper, u32, u32, u32) -> u64, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | f4: extern "cmse-nonsecure-call" fn(Wrapper, u32, u32, u32) -> u64, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/generics.rs:26:73 +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/generics.rs:26:71 | -LL | type WithTraitObject = extern "C-cmse-nonsecure-call" fn(&dyn Trait) -> &dyn Trait; - | ^^^^^^^^^^ this type doesn't fit in the available registers +LL | type WithTraitObject = extern "cmse-nonsecure-call" fn(&dyn Trait) -> &dyn Trait; + | ^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/generics.rs:30:62 +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/generics.rs:30:60 | -LL | extern "C-cmse-nonsecure-call" fn(&'static dyn Trait) -> &'static dyn Trait; - | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers +LL | extern "cmse-nonsecure-call" fn(&'static dyn Trait) -> &'static dyn Trait; + | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/generics.rs:37:62 +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/generics.rs:37:60 | -LL | extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTransparent; - | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers +LL | extern "cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTransparent; + | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0045]: C-variadic functions with the "C-cmse-nonsecure-call" calling convention are not supported +error[E0045]: C-variadic functions with the "cmse-nonsecure-call" calling convention are not supported --> $DIR/generics.rs:40:20 | -LL | type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention +LL | type WithVarArgs = extern "cmse-nonsecure-call" fn(u32, ...); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention error: aborting due to 9 previous errors diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs index 8328f9b6dd55..7036cd367e40 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs @@ -1,7 +1,7 @@ //@ add-core-stubs //@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib //@ needs-llvm-components: arm -#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items)] +#![feature(abi_cmse_nonsecure_call, no_core, lang_items)] #![no_core] extern crate minicore; @@ -13,10 +13,10 @@ pub struct AlignRelevant(u32); #[no_mangle] pub fn test( - f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, x: u32, y: u32), //~ ERROR [E0798] - f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16), //~ ERROR [E0798] - f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32), //~ ERROR [E0798] - f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32), //~ ERROR [E0798] - f5: extern "C-cmse-nonsecure-call" fn([u32; 5]), //~ ERROR [E0798] + f1: extern "cmse-nonsecure-call" fn(u32, u32, u32, u32, x: u32, y: u32), //~ ERROR [E0798] + f2: extern "cmse-nonsecure-call" fn(u32, u32, u32, u16, u16), //~ ERROR [E0798] + f3: extern "cmse-nonsecure-call" fn(u32, u64, u32), //~ ERROR [E0798] + f4: extern "cmse-nonsecure-call" fn(AlignRelevant, u32), //~ ERROR [E0798] + f5: extern "cmse-nonsecure-call" fn([u32; 5]), //~ ERROR [E0798] ) { } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr index 10a5e8561075..5d59405fbd1b 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr @@ -1,42 +1,42 @@ -error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/params-via-stack.rs:16:63 +error[E0798]: arguments for `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/params-via-stack.rs:16:61 | -LL | f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, x: u32, y: u32), - | ^^^^^^^^^^^^^^ these arguments don't fit in the available registers +LL | f1: extern "cmse-nonsecure-call" fn(u32, u32, u32, u32, x: u32, y: u32), + | ^^^^^^^^^^^^^^ these arguments don't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers -error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/params-via-stack.rs:17:63 +error[E0798]: arguments for `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/params-via-stack.rs:17:61 | -LL | f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16), - | ^^^ this argument doesn't fit in the available registers +LL | f2: extern "cmse-nonsecure-call" fn(u32, u32, u32, u16, u16), + | ^^^ this argument doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers -error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/params-via-stack.rs:18:53 +error[E0798]: arguments for `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/params-via-stack.rs:18:51 | -LL | f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32), - | ^^^ this argument doesn't fit in the available registers +LL | f3: extern "cmse-nonsecure-call" fn(u32, u64, u32), + | ^^^ this argument doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers -error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/params-via-stack.rs:19:58 +error[E0798]: arguments for `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/params-via-stack.rs:19:56 | -LL | f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32), - | ^^^ this argument doesn't fit in the available registers +LL | f4: extern "cmse-nonsecure-call" fn(AlignRelevant, u32), + | ^^^ this argument doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers -error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/params-via-stack.rs:20:43 +error[E0798]: arguments for `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/params-via-stack.rs:20:41 | -LL | f5: extern "C-cmse-nonsecure-call" fn([u32; 5]), - | ^^^^^^^^ this argument doesn't fit in the available registers +LL | f5: extern "cmse-nonsecure-call" fn([u32; 5]), + | ^^^^^^^^ this argument doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers error: aborting due to 5 previous errors diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs index 890ec4b00f6a..77347b04ede8 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs @@ -3,7 +3,7 @@ //@ needs-llvm-components: arm //@ add-core-stubs -#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items)] +#![feature(abi_cmse_nonsecure_call, no_core, lang_items)] #![no_core] extern crate minicore; @@ -23,18 +23,18 @@ pub struct ReprCAlign16(u16); #[no_mangle] pub fn test( - f1: extern "C-cmse-nonsecure-call" fn() -> ReprCU64, //~ ERROR [E0798] - f2: extern "C-cmse-nonsecure-call" fn() -> ReprCBytes, //~ ERROR [E0798] - f3: extern "C-cmse-nonsecure-call" fn() -> U64Compound, //~ ERROR [E0798] - f4: extern "C-cmse-nonsecure-call" fn() -> ReprCAlign16, //~ ERROR [E0798] - f5: extern "C-cmse-nonsecure-call" fn() -> [u8; 5], //~ ERROR [E0798] + f1: extern "cmse-nonsecure-call" fn() -> ReprCU64, //~ ERROR [E0798] + f2: extern "cmse-nonsecure-call" fn() -> ReprCBytes, //~ ERROR [E0798] + f3: extern "cmse-nonsecure-call" fn() -> U64Compound, //~ ERROR [E0798] + f4: extern "cmse-nonsecure-call" fn() -> ReprCAlign16, //~ ERROR [E0798] + f5: extern "cmse-nonsecure-call" fn() -> [u8; 5], //~ ERROR [E0798] ) { } #[allow(improper_ctypes_definitions)] struct Test { - u128: extern "C-cmse-nonsecure-call" fn() -> u128, //~ ERROR [E0798] - i128: extern "C-cmse-nonsecure-call" fn() -> i128, //~ ERROR [E0798] + u128: extern "cmse-nonsecure-call" fn() -> u128, //~ ERROR [E0798] + i128: extern "cmse-nonsecure-call" fn() -> i128, //~ ERROR [E0798] } #[repr(C)] @@ -49,7 +49,7 @@ pub union ReprRustUnionU64 { #[no_mangle] pub fn test_union( - f1: extern "C-cmse-nonsecure-call" fn() -> ReprRustUnionU64, //~ ERROR [E0798] - f2: extern "C-cmse-nonsecure-call" fn() -> ReprCUnionU64, //~ ERROR [E0798] + f1: extern "cmse-nonsecure-call" fn() -> ReprRustUnionU64, //~ ERROR [E0798] + f2: extern "cmse-nonsecure-call" fn() -> ReprCUnionU64, //~ ERROR [E0798] ) { } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr index d2077352900a..ddf969c1bce1 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr @@ -1,82 +1,82 @@ -error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:36:50 +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:36:48 | -LL | u128: extern "C-cmse-nonsecure-call" fn() -> u128, - | ^^^^ this type doesn't fit in the available registers +LL | u128: extern "cmse-nonsecure-call" fn() -> u128, + | ^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:37:50 +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:37:48 | -LL | i128: extern "C-cmse-nonsecure-call" fn() -> i128, - | ^^^^ this type doesn't fit in the available registers +LL | i128: extern "cmse-nonsecure-call" fn() -> i128, + | ^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:26:48 +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:26:46 | -LL | f1: extern "C-cmse-nonsecure-call" fn() -> ReprCU64, - | ^^^^^^^^ this type doesn't fit in the available registers +LL | f1: extern "cmse-nonsecure-call" fn() -> ReprCU64, + | ^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:27:48 +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:27:46 | -LL | f2: extern "C-cmse-nonsecure-call" fn() -> ReprCBytes, - | ^^^^^^^^^^ this type doesn't fit in the available registers +LL | f2: extern "cmse-nonsecure-call" fn() -> ReprCBytes, + | ^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:28:48 +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:28:46 | -LL | f3: extern "C-cmse-nonsecure-call" fn() -> U64Compound, - | ^^^^^^^^^^^ this type doesn't fit in the available registers +LL | f3: extern "cmse-nonsecure-call" fn() -> U64Compound, + | ^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:29:48 +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:29:46 | -LL | f4: extern "C-cmse-nonsecure-call" fn() -> ReprCAlign16, - | ^^^^^^^^^^^^ this type doesn't fit in the available registers +LL | f4: extern "cmse-nonsecure-call" fn() -> ReprCAlign16, + | ^^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:30:48 +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:30:46 | -LL | f5: extern "C-cmse-nonsecure-call" fn() -> [u8; 5], - | ^^^^^^^ this type doesn't fit in the available registers +LL | f5: extern "cmse-nonsecure-call" fn() -> [u8; 5], + | ^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:52:48 +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:52:46 | -LL | f1: extern "C-cmse-nonsecure-call" fn() -> ReprRustUnionU64, - | ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers +LL | f1: extern "cmse-nonsecure-call" fn() -> ReprRustUnionU64, + | ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:53:48 +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:53:46 | -LL | f2: extern "C-cmse-nonsecure-call" fn() -> ReprCUnionU64, - | ^^^^^^^^^^^^^ this type doesn't fit in the available registers +LL | f2: extern "cmse-nonsecure-call" fn() -> ReprCUnionU64, + | ^^^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size error: aborting due to 9 previous errors diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/via-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/via-registers.rs index 7dfe6cf9672a..419d26875bcd 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/via-registers.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/via-registers.rs @@ -2,7 +2,7 @@ //@ build-pass //@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib //@ needs-llvm-components: arm -#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)] +#![feature(abi_cmse_nonsecure_call, no_core, lang_items, intrinsics)] #![no_core] extern crate minicore; @@ -27,26 +27,26 @@ pub struct U32Compound(u16, u16); #[no_mangle] #[allow(improper_ctypes_definitions)] pub fn params( - f1: extern "C-cmse-nonsecure-call" fn(), - f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32), - f3: extern "C-cmse-nonsecure-call" fn(u64, u64), - f4: extern "C-cmse-nonsecure-call" fn(u128), - f5: extern "C-cmse-nonsecure-call" fn(f64, f32, f32), - f6: extern "C-cmse-nonsecure-call" fn(ReprTransparentStruct, U32Compound), - f7: extern "C-cmse-nonsecure-call" fn([u32; 4]), + f1: extern "cmse-nonsecure-call" fn(), + f2: extern "cmse-nonsecure-call" fn(u32, u32, u32, u32), + f3: extern "cmse-nonsecure-call" fn(u64, u64), + f4: extern "cmse-nonsecure-call" fn(u128), + f5: extern "cmse-nonsecure-call" fn(f64, f32, f32), + f6: extern "cmse-nonsecure-call" fn(ReprTransparentStruct, U32Compound), + f7: extern "cmse-nonsecure-call" fn([u32; 4]), ) { } #[no_mangle] pub fn returns( - f1: extern "C-cmse-nonsecure-call" fn() -> u32, - f2: extern "C-cmse-nonsecure-call" fn() -> u64, - f3: extern "C-cmse-nonsecure-call" fn() -> i64, - f4: extern "C-cmse-nonsecure-call" fn() -> f64, - f5: extern "C-cmse-nonsecure-call" fn() -> [u8; 4], - f6: extern "C-cmse-nonsecure-call" fn() -> ReprTransparentStruct, - f7: extern "C-cmse-nonsecure-call" fn() -> ReprTransparentStruct>, - f8: extern "C-cmse-nonsecure-call" fn() -> ReprTransparentEnumU64, - f9: extern "C-cmse-nonsecure-call" fn() -> U32Compound, + f1: extern "cmse-nonsecure-call" fn() -> u32, + f2: extern "cmse-nonsecure-call" fn() -> u64, + f3: extern "cmse-nonsecure-call" fn() -> i64, + f4: extern "cmse-nonsecure-call" fn() -> f64, + f5: extern "cmse-nonsecure-call" fn() -> [u8; 4], + f6: extern "cmse-nonsecure-call" fn() -> ReprTransparentStruct, + f7: extern "cmse-nonsecure-call" fn() -> ReprTransparentStruct>, + f8: extern "cmse-nonsecure-call" fn() -> ReprTransparentEnumU64, + f9: extern "cmse-nonsecure-call" fn() -> U32Compound, ) { } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs index 5a2d2db19c54..44a1e7d69a8c 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs @@ -1,10 +1,10 @@ //@ add-core-stubs //@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib //@ needs-llvm-components: arm -#![feature(abi_c_cmse_nonsecure_call, lang_items, no_core)] +#![feature(abi_cmse_nonsecure_call, lang_items, no_core)] #![no_core] extern crate minicore; use minicore::*; -pub extern "C-cmse-nonsecure-call" fn test() {} //~ ERROR [E0781] +pub extern "cmse-nonsecure-call" fn test() {} //~ ERROR [E0781] diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr index f49fab043a47..b9cccecc64bf 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr @@ -1,8 +1,8 @@ -error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers +error[E0781]: the `"cmse-nonsecure-call"` ABI is only allowed on function pointers --> $DIR/wrong-abi-location-1.rs:10:1 | -LL | pub extern "C-cmse-nonsecure-call" fn test() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub extern "cmse-nonsecure-call" fn test() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs index e93b153949a3..f23f45f786fb 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs @@ -1,12 +1,12 @@ //@ add-core-stubs //@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib //@ needs-llvm-components: arm -#![feature(abi_c_cmse_nonsecure_call, lang_items, no_core)] +#![feature(abi_cmse_nonsecure_call, lang_items, no_core)] #![no_core] extern crate minicore; use minicore::*; -extern "C-cmse-nonsecure-call" { //~ ERROR [E0781] +extern "cmse-nonsecure-call" { //~ ERROR [E0781] fn test(); } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr index bae8d20d81c5..437d7b80b1fd 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr @@ -1,7 +1,7 @@ -error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers +error[E0781]: the `"cmse-nonsecure-call"` ABI is only allowed on function pointers --> $DIR/wrong-abi-location-2.rs:10:1 | -LL | / extern "C-cmse-nonsecure-call" { +LL | / extern "cmse-nonsecure-call" { LL | | fn test(); LL | | } | |_^ diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs index 6061451b2e97..8ec22033a3df 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs @@ -1,9 +1,9 @@ // gate-test-cmse_nonsecure_entry #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { - //~^ ERROR [E0570] - //~| ERROR [E0658] +pub extern "cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + //~^ ERROR: is not a supported ABI for the current target [E0570] + //~| ERROR: ABI is experimental and subject to change [E0658] input + 6 } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr index 0afbbe647af0..e40862e74eee 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr @@ -1,19 +1,19 @@ -error[E0658]: the extern "C-cmse-nonsecure-entry" ABI is experimental and subject to change +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target --> $DIR/gate_test.rs:4:12 | -LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub extern "cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0658]: the extern "cmse-nonsecure-entry" ABI is experimental and subject to change + --> $DIR/gate_test.rs:4:12 + | +LL | pub extern "cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #75835 for more information = help: add `#![feature(cmse_nonsecure_entry)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/gate_test.rs:4:1 - | -LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: aborting due to 2 previous errors Some errors have detailed explanations: E0570, E0658. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs index 19b6179dde75..800dd580af29 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs @@ -11,12 +11,12 @@ use minicore::*; struct Wrapper(T); impl Wrapper { - extern "C-cmse-nonsecure-entry" fn ambient_generic(_: T, _: u32, _: u32, _: u32) -> u64 { + extern "cmse-nonsecure-entry" fn ambient_generic(_: T, _: u32, _: u32, _: u32) -> u64 { //~^ ERROR [E0798] 0 } - extern "C-cmse-nonsecure-entry" fn ambient_generic_nested( + extern "cmse-nonsecure-entry" fn ambient_generic_nested( //~^ ERROR [E0798] _: Wrapper, _: u32, @@ -27,7 +27,7 @@ impl Wrapper { } } -extern "C-cmse-nonsecure-entry" fn introduced_generic( +extern "cmse-nonsecure-entry" fn introduced_generic( //~^ ERROR [E0798] _: U, _: u32, @@ -37,40 +37,40 @@ extern "C-cmse-nonsecure-entry" fn introduced_generic( 0 } -extern "C-cmse-nonsecure-entry" fn impl_trait(_: impl Copy, _: u32, _: u32, _: u32) -> u64 { +extern "cmse-nonsecure-entry" fn impl_trait(_: impl Copy, _: u32, _: u32, _: u32) -> u64 { //~^ ERROR [E0798] 0 } -extern "C-cmse-nonsecure-entry" fn reference(x: &usize) -> usize { +extern "cmse-nonsecure-entry" fn reference(x: &usize) -> usize { *x } trait Trait {} -extern "C-cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait { - //~^ ERROR return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers [E0798] +extern "cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait { + //~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798] x } -extern "C-cmse-nonsecure-entry" fn static_trait_object( +extern "cmse-nonsecure-entry" fn static_trait_object( x: &'static dyn Trait, ) -> &'static dyn Trait { - //~^ ERROR return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers [E0798] + //~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798] x } #[repr(transparent)] struct WrapperTransparent<'a>(&'a dyn Trait); -extern "C-cmse-nonsecure-entry" fn wrapped_trait_object( +extern "cmse-nonsecure-entry" fn wrapped_trait_object( x: WrapperTransparent, ) -> WrapperTransparent { - //~^ ERROR return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers [E0798] + //~^ ERROR return value of `"cmse-nonsecure-entry"` function too large to pass via registers [E0798] x } -extern "C-cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { +extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg //~| ERROR requires `va_list` lang_item } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr index c314671dc297..f0190671b5a1 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr @@ -1,13 +1,13 @@ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg - --> $DIR/generics.rs:73:55 + --> $DIR/generics.rs:73:53 | -LL | extern "C-cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { - | ^^^^^^ +LL | extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { + | ^^^^^^ -error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type +error[E0798]: functions with the `"cmse-nonsecure-entry"` ABI cannot contain generics in their type --> $DIR/generics.rs:30:1 | -LL | / extern "C-cmse-nonsecure-entry" fn introduced_generic( +LL | / extern "cmse-nonsecure-entry" fn introduced_generic( LL | | LL | | _: U, LL | | _: u32, @@ -16,22 +16,22 @@ LL | | _: u32, LL | | ) -> u64 { | |________^ -error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type +error[E0798]: functions with the `"cmse-nonsecure-entry"` ABI cannot contain generics in their type --> $DIR/generics.rs:40:1 | -LL | extern "C-cmse-nonsecure-entry" fn impl_trait(_: impl Copy, _: u32, _: u32, _: u32) -> u64 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | extern "cmse-nonsecure-entry" fn impl_trait(_: impl Copy, _: u32, _: u32, _: u32) -> u64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type +error[E0798]: functions with the `"cmse-nonsecure-entry"` ABI cannot contain generics in their type --> $DIR/generics.rs:14:5 | -LL | extern "C-cmse-nonsecure-entry" fn ambient_generic(_: T, _: u32, _: u32, _: u32) -> u64 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | extern "cmse-nonsecure-entry" fn ambient_generic(_: T, _: u32, _: u32, _: u32) -> u64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type +error[E0798]: functions with the `"cmse-nonsecure-entry"` ABI cannot contain generics in their type --> $DIR/generics.rs:19:5 | -LL | / extern "C-cmse-nonsecure-entry" fn ambient_generic_nested( +LL | / extern "cmse-nonsecure-entry" fn ambient_generic_nested( LL | | LL | | _: Wrapper, LL | | _: u32, @@ -40,38 +40,38 @@ LL | | _: u32, LL | | ) -> u64 { | |____________^ -error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/generics.rs:51:67 +error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/generics.rs:51:65 | -LL | extern "C-cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait { - | ^^^^^^^^^^ this type doesn't fit in the available registers +LL | extern "cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait { + | ^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers +error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers --> $DIR/generics.rs:58:6 | LL | ) -> &'static dyn Trait { | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers +error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers --> $DIR/generics.rs:68:6 | LL | ) -> WrapperTransparent { | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size error: requires `va_list` lang_item - --> $DIR/generics.rs:73:55 + --> $DIR/generics.rs:73:53 | -LL | extern "C-cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { - | ^^^^^^ +LL | extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { + | ^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs index 4c53f9422dab..d4f722fa1938 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs @@ -12,14 +12,14 @@ use minicore::*; pub struct AlignRelevant(u32); #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn f1(_: u32, _: u32, _: u32, _: u32, _: u32, _: u32) {} //~ ERROR [E0798] +pub extern "cmse-nonsecure-entry" fn f1(_: u32, _: u32, _: u32, _: u32, _: u32, _: u32) {} //~ ERROR [E0798] #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn f2(_: u32, _: u32, _: u32, _: u16, _: u16) {} //~ ERROR [E0798] +pub extern "cmse-nonsecure-entry" fn f2(_: u32, _: u32, _: u32, _: u16, _: u16) {} //~ ERROR [E0798] #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn f3(_: u32, _: u64, _: u32) {} //~ ERROR [E0798] +pub extern "cmse-nonsecure-entry" fn f3(_: u32, _: u64, _: u32) {} //~ ERROR [E0798] #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn f4(_: AlignRelevant, _: u32) {} //~ ERROR [E0798] +pub extern "cmse-nonsecure-entry" fn f4(_: AlignRelevant, _: u32) {} //~ ERROR [E0798] #[no_mangle] #[allow(improper_ctypes_definitions)] -pub extern "C-cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} //~ ERROR [E0798] +pub extern "cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} //~ ERROR [E0798] diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr index 24e9ddf32feb..f8b96bddc947 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr @@ -1,42 +1,42 @@ -error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/params-via-stack.rs:15:78 +error[E0798]: arguments for `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:15:76 | -LL | pub extern "C-cmse-nonsecure-entry" fn f1(_: u32, _: u32, _: u32, _: u32, _: u32, _: u32) {} - | ^^^^^^^^^^^ these arguments don't fit in the available registers +LL | pub extern "cmse-nonsecure-entry" fn f1(_: u32, _: u32, _: u32, _: u32, _: u32, _: u32) {} + | ^^^^^^^^^^^ these arguments don't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers -error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/params-via-stack.rs:17:78 +error[E0798]: arguments for `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:17:76 | -LL | pub extern "C-cmse-nonsecure-entry" fn f2(_: u32, _: u32, _: u32, _: u16, _: u16) {} - | ^^^ this argument doesn't fit in the available registers +LL | pub extern "cmse-nonsecure-entry" fn f2(_: u32, _: u32, _: u32, _: u16, _: u16) {} + | ^^^ this argument doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers -error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/params-via-stack.rs:19:62 +error[E0798]: arguments for `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:19:60 | -LL | pub extern "C-cmse-nonsecure-entry" fn f3(_: u32, _: u64, _: u32) {} +LL | pub extern "cmse-nonsecure-entry" fn f3(_: u32, _: u64, _: u32) {} + | ^^^ this argument doesn't fit in the available registers + | + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + +error[E0798]: arguments for `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:21:62 + | +LL | pub extern "cmse-nonsecure-entry" fn f4(_: AlignRelevant, _: u32) {} | ^^^ this argument doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers -error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/params-via-stack.rs:21:64 +error[E0798]: arguments for `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:25:44 | -LL | pub extern "C-cmse-nonsecure-entry" fn f4(_: AlignRelevant, _: u32) {} - | ^^^ this argument doesn't fit in the available registers +LL | pub extern "cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} + | ^^^^^^^^ this argument doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers - -error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/params-via-stack.rs:25:46 - | -LL | pub extern "C-cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} - | ^^^^^^^^ this argument doesn't fit in the available registers - | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers error: aborting due to 5 previous errors diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.rs index 735eab10fa15..0052a0977ed7 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.rs @@ -22,41 +22,41 @@ pub struct U64Compound(u32, u32); pub struct ReprCAlign16(u16); #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn f1() -> ReprCU64 { +pub extern "cmse-nonsecure-entry" fn f1() -> ReprCU64 { //~^ ERROR [E0798] ReprCU64(0) } #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn f2() -> ReprCBytes { +pub extern "cmse-nonsecure-entry" fn f2() -> ReprCBytes { //~^ ERROR [E0798] ReprCBytes(0, 1, 2, 3, 4) } #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn f3() -> U64Compound { +pub extern "cmse-nonsecure-entry" fn f3() -> U64Compound { //~^ ERROR [E0798] U64Compound(2, 3) } #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn f4() -> ReprCAlign16 { +pub extern "cmse-nonsecure-entry" fn f4() -> ReprCAlign16 { //~^ ERROR [E0798] ReprCAlign16(4) } #[no_mangle] #[allow(improper_ctypes_definitions)] -pub extern "C-cmse-nonsecure-entry" fn f5() -> [u8; 5] { +pub extern "cmse-nonsecure-entry" fn f5() -> [u8; 5] { //~^ ERROR [E0798] [0xAA; 5] } #[no_mangle] #[allow(improper_ctypes_definitions)] -pub extern "C-cmse-nonsecure-entry" fn u128() -> u128 { +pub extern "cmse-nonsecure-entry" fn u128() -> u128 { //~^ ERROR [E0798] 123 } #[no_mangle] #[allow(improper_ctypes_definitions)] -pub extern "C-cmse-nonsecure-entry" fn i128() -> i128 { +pub extern "cmse-nonsecure-entry" fn i128() -> i128 { //~^ ERROR [E0798] 456 } @@ -73,12 +73,12 @@ pub union ReprCUnionU64 { #[no_mangle] #[allow(improper_ctypes_definitions)] -pub extern "C-cmse-nonsecure-entry" fn union_rust() -> ReprRustUnionU64 { +pub extern "cmse-nonsecure-entry" fn union_rust() -> ReprRustUnionU64 { //~^ ERROR [E0798] ReprRustUnionU64 { _unused: 1 } } #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn union_c() -> ReprCUnionU64 { +pub extern "cmse-nonsecure-entry" fn union_c() -> ReprCUnionU64 { //~^ ERROR [E0798] ReprCUnionU64 { _unused: 2 } } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.stderr index 9c885d953181..c5effed92ae9 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.stderr @@ -1,82 +1,82 @@ -error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/return-via-stack.rs:25:48 +error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:25:46 | -LL | pub extern "C-cmse-nonsecure-entry" fn f1() -> ReprCU64 { - | ^^^^^^^^ this type doesn't fit in the available registers +LL | pub extern "cmse-nonsecure-entry" fn f1() -> ReprCU64 { + | ^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/return-via-stack.rs:30:48 +error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:30:46 | -LL | pub extern "C-cmse-nonsecure-entry" fn f2() -> ReprCBytes { - | ^^^^^^^^^^ this type doesn't fit in the available registers +LL | pub extern "cmse-nonsecure-entry" fn f2() -> ReprCBytes { + | ^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/return-via-stack.rs:35:48 +error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:35:46 | -LL | pub extern "C-cmse-nonsecure-entry" fn f3() -> U64Compound { - | ^^^^^^^^^^^ this type doesn't fit in the available registers +LL | pub extern "cmse-nonsecure-entry" fn f3() -> U64Compound { + | ^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/return-via-stack.rs:40:48 +error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:40:46 | -LL | pub extern "C-cmse-nonsecure-entry" fn f4() -> ReprCAlign16 { - | ^^^^^^^^^^^^ this type doesn't fit in the available registers +LL | pub extern "cmse-nonsecure-entry" fn f4() -> ReprCAlign16 { + | ^^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/return-via-stack.rs:47:48 +error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:47:46 | -LL | pub extern "C-cmse-nonsecure-entry" fn f5() -> [u8; 5] { - | ^^^^^^^ this type doesn't fit in the available registers +LL | pub extern "cmse-nonsecure-entry" fn f5() -> [u8; 5] { + | ^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/return-via-stack.rs:53:50 +error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:53:48 | -LL | pub extern "C-cmse-nonsecure-entry" fn u128() -> u128 { - | ^^^^ this type doesn't fit in the available registers +LL | pub extern "cmse-nonsecure-entry" fn u128() -> u128 { + | ^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/return-via-stack.rs:59:50 +error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:59:48 | -LL | pub extern "C-cmse-nonsecure-entry" fn i128() -> i128 { - | ^^^^ this type doesn't fit in the available registers +LL | pub extern "cmse-nonsecure-entry" fn i128() -> i128 { + | ^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/return-via-stack.rs:76:56 +error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:76:54 | -LL | pub extern "C-cmse-nonsecure-entry" fn union_rust() -> ReprRustUnionU64 { - | ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers +LL | pub extern "cmse-nonsecure-entry" fn union_rust() -> ReprRustUnionU64 { + | ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers - --> $DIR/return-via-stack.rs:81:53 +error[E0798]: return value of `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:81:51 | -LL | pub extern "C-cmse-nonsecure-entry" fn union_c() -> ReprCUnionU64 { - | ^^^^^^^^^^^^^ this type doesn't fit in the available registers +LL | pub extern "cmse-nonsecure-entry" fn union_c() -> ReprCUnionU64 { + | ^^^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size error: aborting due to 9 previous errors diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr index 6a90dc8d635b..3949eac15429 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr @@ -1,8 +1,8 @@ -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/trustzone-only.rs:17:1 +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/trustzone-only.rs:17:12 | -LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub extern "cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs index 6d84dab2166e..ff5d2ec0ab6c 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs @@ -14,7 +14,7 @@ extern crate minicore; use minicore::*; #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { +pub extern "cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { //~^ ERROR [E0570] input } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr index 6a90dc8d635b..3949eac15429 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr @@ -1,8 +1,8 @@ -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/trustzone-only.rs:17:1 +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/trustzone-only.rs:17:12 | -LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub extern "cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr index 6a90dc8d635b..3949eac15429 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr @@ -1,8 +1,8 @@ -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/trustzone-only.rs:17:1 +error[E0570]: "cmse-nonsecure-entry" is not a supported ABI for the current target + --> $DIR/trustzone-only.rs:17:12 | -LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub extern "cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs index 912fc8b85ebd..343732881256 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs @@ -26,49 +26,49 @@ pub enum ReprTransparentEnumU64 { pub struct U32Compound(u16, u16); #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn inputs1() {} +pub extern "cmse-nonsecure-entry" fn inputs1() {} #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn inputs2(_: u32, _: u32, _: u32, _: u32) {} +pub extern "cmse-nonsecure-entry" fn inputs2(_: u32, _: u32, _: u32, _: u32) {} #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn inputs3(_: u64, _: u64) {} +pub extern "cmse-nonsecure-entry" fn inputs3(_: u64, _: u64) {} #[no_mangle] #[allow(improper_ctypes_definitions)] -pub extern "C-cmse-nonsecure-entry" fn inputs4(_: u128) {} +pub extern "cmse-nonsecure-entry" fn inputs4(_: u128) {} #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn inputs5(_: f64, _: f32, _: f32) {} +pub extern "cmse-nonsecure-entry" fn inputs5(_: f64, _: f32, _: f32) {} #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn inputs6(_: ReprTransparentStruct, _: U32Compound) {} +pub extern "cmse-nonsecure-entry" fn inputs6(_: ReprTransparentStruct, _: U32Compound) {} #[no_mangle] #[allow(improper_ctypes_definitions)] -pub extern "C-cmse-nonsecure-entry" fn inputs7(_: [u32; 4]) {} +pub extern "cmse-nonsecure-entry" fn inputs7(_: [u32; 4]) {} #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn outputs1() -> u32 { +pub extern "cmse-nonsecure-entry" fn outputs1() -> u32 { 0 } #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn outputs2() -> u64 { +pub extern "cmse-nonsecure-entry" fn outputs2() -> u64 { 0 } #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn outputs3() -> i64 { +pub extern "cmse-nonsecure-entry" fn outputs3() -> i64 { 0 } #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn outputs4() -> f64 { +pub extern "cmse-nonsecure-entry" fn outputs4() -> f64 { 0.0 } #[no_mangle] #[allow(improper_ctypes_definitions)] -pub extern "C-cmse-nonsecure-entry" fn outputs5() -> [u8; 4] { +pub extern "cmse-nonsecure-entry" fn outputs5() -> [u8; 4] { [0xAA; 4] } #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn outputs6() -> ReprTransparentStruct { +pub extern "cmse-nonsecure-entry" fn outputs6() -> ReprTransparentStruct { ReprTransparentStruct { _marker1: (), _marker2: (), field: 0xAA, _marker3: () } } #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn outputs7( +pub extern "cmse-nonsecure-entry" fn outputs7( ) -> ReprTransparentStruct> { ReprTransparentStruct { _marker1: (), @@ -78,10 +78,10 @@ pub extern "C-cmse-nonsecure-entry" fn outputs7( } } #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn outputs8() -> ReprTransparentEnumU64 { +pub extern "cmse-nonsecure-entry" fn outputs8() -> ReprTransparentEnumU64 { ReprTransparentEnumU64::A(0) } #[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn outputs9() -> U32Compound { +pub extern "cmse-nonsecure-entry" fn outputs9() -> U32Compound { U32Compound(1, 2) } diff --git a/tests/ui/coercion/invalid-blanket-coerce-unsized-impl.rs b/tests/ui/coercion/invalid-blanket-coerce-unsized-impl.rs new file mode 100644 index 000000000000..a4fd77107188 --- /dev/null +++ b/tests/ui/coercion/invalid-blanket-coerce-unsized-impl.rs @@ -0,0 +1,13 @@ +// Regression test minimized from #126982. +// We used to apply a coerce_unsized coercion to literally every argument since +// the blanket applied in literally all cases, even though it was incoherent. + +#![feature(coerce_unsized)] + +impl std::ops::CoerceUnsized for A {} +//~^ ERROR type parameter `A` must be used as the type parameter for some local type +//~| ERROR the trait `CoerceUnsized` may only be implemented for a coercion between structures + +const C: usize = 1; + +fn main() {} diff --git a/tests/ui/coercion/invalid-blanket-coerce-unsized-impl.stderr b/tests/ui/coercion/invalid-blanket-coerce-unsized-impl.stderr new file mode 100644 index 000000000000..377906ee334a --- /dev/null +++ b/tests/ui/coercion/invalid-blanket-coerce-unsized-impl.stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/invalid-blanket-coerce-unsized-impl.rs:7:6 + | +LL | impl std::ops::CoerceUnsized for A {} + | ^ type parameter `A` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0377]: the trait `CoerceUnsized` may only be implemented for a coercion between structures + --> $DIR/invalid-blanket-coerce-unsized-impl.rs:7:1 + | +LL | impl std::ops::CoerceUnsized for A {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0210, E0377. +For more information about an error, try `rustc --explain E0210`. diff --git a/tests/ui/compiletest-self-test/line-annotation-mismatches.rs b/tests/ui/compiletest-self-test/line-annotation-mismatches.rs new file mode 100644 index 000000000000..d2a14374ed4c --- /dev/null +++ b/tests/ui/compiletest-self-test/line-annotation-mismatches.rs @@ -0,0 +1,42 @@ +//@ should-fail + +// The warning is reported with unknown line +//@ compile-flags: -D raw_pointer_derive +//~? WARN kind and unknown line match the reported warning, but we do not suggest it + +// The error is expected but not reported at all. +//~ ERROR this error does not exist + +// The error is reported but not expected at all. +// "`main` function not found in crate" (the main function is intentionally not added) + +// An "unimportant" diagnostic is expected on a wrong line. +//~ ERROR aborting due to + +// An "unimportant" diagnostic is expected with a wrong kind. +//~? ERROR For more information about an error + +fn wrong_line_or_kind() { + // A diagnostic expected on a wrong line. + unresolved1; + //~ ERROR cannot find value `unresolved1` in this scope + + // A diagnostic expected with a wrong kind. + unresolved2; //~ WARN cannot find value `unresolved2` in this scope + + // A diagnostic expected with a missing kind (treated as a wrong kind). + unresolved3; //~ cannot find value `unresolved3` in this scope + + // A diagnostic expected with a wrong line and kind. + unresolved4; + //~ WARN cannot find value `unresolved4` in this scope +} + +fn wrong_message() { + // A diagnostic expected with a wrong message, but the line is known and right. + unresolvedA; //~ ERROR stub message 1 + + // A diagnostic expected with a wrong message, but the line is known and right, + // even if the kind doesn't match. + unresolvedB; //~ WARN stub message 2 +} diff --git a/tests/ui/compiletest-self-test/line-annotation-mismatches.stderr b/tests/ui/compiletest-self-test/line-annotation-mismatches.stderr new file mode 100644 index 000000000000..7ca3bfaf396c --- /dev/null +++ b/tests/ui/compiletest-self-test/line-annotation-mismatches.stderr @@ -0,0 +1,61 @@ +warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok + | + = note: requested on the command line with `-D raw_pointer_derive` + = note: `#[warn(renamed_and_removed_lints)]` on by default + +error[E0425]: cannot find value `unresolved1` in this scope + --> $DIR/line-annotation-mismatches.rs:21:5 + | +LL | unresolved1; + | ^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `unresolved2` in this scope + --> $DIR/line-annotation-mismatches.rs:25:5 + | +LL | unresolved2; + | ^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `unresolved3` in this scope + --> $DIR/line-annotation-mismatches.rs:28:5 + | +LL | unresolved3; + | ^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `unresolved4` in this scope + --> $DIR/line-annotation-mismatches.rs:31:5 + | +LL | unresolved4; + | ^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `unresolvedA` in this scope + --> $DIR/line-annotation-mismatches.rs:37:5 + | +LL | unresolvedA; + | ^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `unresolvedB` in this scope + --> $DIR/line-annotation-mismatches.rs:41:5 + | +LL | unresolvedB; + | ^^^^^^^^^^^ not found in this scope + +warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok + | + = note: requested on the command line with `-D raw_pointer_derive` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0601]: `main` function not found in crate `line_annotation_mismatches` + --> $DIR/line-annotation-mismatches.rs:42:2 + | +LL | } + | ^ consider adding a `main` function to `$DIR/line-annotation-mismatches.rs` + +warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok + | + = note: requested on the command line with `-D raw_pointer_derive` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 7 previous errors; 3 warnings emitted + +Some errors have detailed explanations: E0425, E0601. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/const-generics/issues/issue-86535-2.rs b/tests/ui/const-generics/issues/issue-86535-2.rs index 8d064f3eeb1b..5c9132fe54d3 100644 --- a/tests/ui/const-generics/issues/issue-86535-2.rs +++ b/tests/ui/const-generics/issues/issue-86535-2.rs @@ -9,7 +9,7 @@ pub trait Foo { [(); Self::ASSOC_C]:; } -struct Bar; +struct Bar; //~ WARN struct `Bar` is never constructed impl Foo for Bar { const ASSOC_C: usize = 3; diff --git a/tests/ui/const-generics/issues/issue-86535-2.stderr b/tests/ui/const-generics/issues/issue-86535-2.stderr new file mode 100644 index 000000000000..0ba748365754 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86535-2.stderr @@ -0,0 +1,10 @@ +warning: struct `Bar` is never constructed + --> $DIR/issue-86535-2.rs:12:8 + | +LL | struct Bar; + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/issues/issue-86535.rs b/tests/ui/const-generics/issues/issue-86535.rs index 62454f4a388a..2cdf801c1561 100644 --- a/tests/ui/const-generics/issues/issue-86535.rs +++ b/tests/ui/const-generics/issues/issue-86535.rs @@ -2,7 +2,7 @@ #![feature(adt_const_params, unsized_const_params, generic_const_exprs)] #![allow(incomplete_features, unused_variables)] -struct F; +struct F; //~ WARN struct `F` is never constructed impl X for F<{ S }> { const W: usize = 3; diff --git a/tests/ui/const-generics/issues/issue-86535.stderr b/tests/ui/const-generics/issues/issue-86535.stderr new file mode 100644 index 000000000000..84d6c1c11ff6 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86535.stderr @@ -0,0 +1,10 @@ +warning: struct `F` is never constructed + --> $DIR/issue-86535.rs:5:8 + | +LL | struct F; + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/consts/const-eval/format.stderr b/tests/ui/consts/const-eval/format.stderr index 2f202705b7f9..bd50ac0bf411 100644 --- a/tests/ui/consts/const-eval/format.stderr +++ b/tests/ui/consts/const-eval/format.stderr @@ -13,7 +13,7 @@ LL | println!("{:?}", 0); | ^^^^^^^^^^^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0015]: cannot call non-const function `_print` in constant functions --> $DIR/format.rs:7:5 diff --git a/tests/ui/consts/const_cmp_type_id.rs b/tests/ui/consts/const_cmp_type_id.rs index e89b8d377878..dca0615083a7 100644 --- a/tests/ui/consts/const_cmp_type_id.rs +++ b/tests/ui/consts/const_cmp_type_id.rs @@ -6,11 +6,10 @@ use std::any::TypeId; fn main() { const { assert!(TypeId::of::() == TypeId::of::()); - //~^ ERROR cannot call non-const operator in constants + //~^ ERROR the trait bound `TypeId: const PartialEq` is not satisfied assert!(TypeId::of::<()>() != TypeId::of::()); - //~^ ERROR cannot call non-const operator in constants + //~^ ERROR the trait bound `TypeId: const PartialEq` is not satisfied let _a = TypeId::of::() < TypeId::of::(); - //~^ ERROR cannot call non-const operator in constants // can't assert `_a` because it is not deterministic // FIXME(const_trait_impl) make it pass } diff --git a/tests/ui/consts/const_cmp_type_id.stderr b/tests/ui/consts/const_cmp_type_id.stderr index 62f8d42c0e68..a8242a200eff 100644 --- a/tests/ui/consts/const_cmp_type_id.stderr +++ b/tests/ui/consts/const_cmp_type_id.stderr @@ -1,33 +1,15 @@ -error[E0015]: cannot call non-const operator in constants +error[E0277]: the trait bound `TypeId: const PartialEq` is not satisfied --> $DIR/const_cmp_type_id.rs:8:17 | LL | assert!(TypeId::of::() == TypeId::of::()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/any.rs:LL:COL - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const operator in constants +error[E0277]: the trait bound `TypeId: const PartialEq` is not satisfied --> $DIR/const_cmp_type_id.rs:10:17 | LL | assert!(TypeId::of::<()>() != TypeId::of::()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/any.rs:LL:COL - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const operator in constants - --> $DIR/const_cmp_type_id.rs:12:18 - | -LL | let _a = TypeId::of::() < TypeId::of::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/any.rs:LL:COL - = note: calls in constants are limited to constant functions, tuple structs and tuple variants +error: aborting due to 2 previous errors -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index d688bfbde2bc..7dc080498896 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -4,12 +4,6 @@ error[E0635]: unknown feature `const_fn_trait_ref_impls` LL | #![feature(const_fn_trait_ref_impls)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0635]: unknown feature `const_cmp` - --> $DIR/fn_trait_refs.rs:7:12 - | -LL | #![feature(const_cmp)] - | ^^^^^^^^^ - error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:14:8 | @@ -155,21 +149,17 @@ note: `FnMut` can't be used with `~const` because it isn't annotated with `#[con --> $SRC_DIR/core/src/ops/function.rs:LL:COL = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0015]: cannot call non-const operator in constants +error[E0277]: the trait bound `(i32, i32, i32): const PartialEq` is not satisfied --> $DIR/fn_trait_refs.rs:71:17 | LL | assert!(test_one == (1, 1, 1)); | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const operator in constants +error[E0277]: the trait bound `(i32, i32): const PartialEq` is not satisfied --> $DIR/fn_trait_refs.rs:74:17 | LL | assert!(test_two == (2, 2)); | ^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants error[E0015]: cannot call non-const closure in constant functions --> $DIR/fn_trait_refs.rs:16:5 @@ -195,7 +185,7 @@ LL | f() | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 22 previous errors +error: aborting due to 21 previous errors -Some errors have detailed explanations: E0015, E0635. +Some errors have detailed explanations: E0015, E0277, E0635. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-73976-monomorphic.stderr b/tests/ui/consts/issue-73976-monomorphic.stderr index ef754b23ff06..e5b32e0c4adf 100644 --- a/tests/ui/consts/issue-73976-monomorphic.stderr +++ b/tests/ui/consts/issue-73976-monomorphic.stderr @@ -1,13 +1,9 @@ -error[E0015]: cannot call non-const operator in constant functions +error[E0277]: the trait bound `TypeId: ~const PartialEq` is not satisfied --> $DIR/issue-73976-monomorphic.rs:21:5 | LL | GetTypeId::::VALUE == GetTypeId::::VALUE | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/any.rs:LL:COL - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/issue-90870.rs b/tests/ui/consts/issue-90870.rs index b62769a33f8e..f807ae75ee5e 100644 --- a/tests/ui/consts/issue-90870.rs +++ b/tests/ui/consts/issue-90870.rs @@ -3,22 +3,31 @@ #![allow(dead_code)] const fn f(a: &u8, b: &u8) -> bool { + //~^ HELP: add `#![feature(const_trait_impl)]` to the crate attributes to enable + //~| HELP: add `#![feature(const_trait_impl)]` to the crate attributes to enable + //~| HELP: add `#![feature(const_trait_impl)]` to the crate attributes to enable a == b - //~^ ERROR: cannot call non-const operator in constant functions [E0015] + //~^ ERROR: cannot call conditionally-const operator in constant functions + //~| ERROR: `PartialEq` is not yet stable as a const trait //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` to the crate attributes to enable } const fn g(a: &&&&i64, b: &&&&i64) -> bool { a == b - //~^ ERROR: cannot call non-const operator in constant functions [E0015] + //~^ ERROR: cannot call conditionally-const operator in constant functions + //~| ERROR: `PartialEq` is not yet stable as a const trait //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` to the crate attributes to enable } const fn h(mut a: &[u8], mut b: &[u8]) -> bool { while let ([l, at @ ..], [r, bt @ ..]) = (a, b) { if l == r { - //~^ ERROR: cannot call non-const operator in constant functions [E0015] + //~^ ERROR: cannot call conditionally-const operator in constant functions + //~| ERROR: `PartialEq` is not yet stable as a const trait //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` to the crate attributes to enable a = at; b = bt; } else { diff --git a/tests/ui/consts/issue-90870.stderr b/tests/ui/consts/issue-90870.stderr index ea987920d7d3..8d6f21fd82fb 100644 --- a/tests/ui/consts/issue-90870.stderr +++ b/tests/ui/consts/issue-90870.stderr @@ -1,39 +1,81 @@ -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/issue-90870.rs:6:5 +error[E0658]: cannot call conditionally-const operator in constant functions + --> $DIR/issue-90870.rs:9:5 | LL | a == b | ^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date help: consider dereferencing here | LL | *a == *b | + + -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/issue-90870.rs:12:5 +error: `PartialEq` is not yet stable as a const trait + --> $DIR/issue-90870.rs:9:5 + | +LL | a == b + | ^^^^^^ + | +help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + | +LL + #![feature(const_trait_impl)] + | + +error[E0658]: cannot call conditionally-const operator in constant functions + --> $DIR/issue-90870.rs:17:5 | LL | a == b | ^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date help: consider dereferencing here | LL | ****a == ****b | ++++ ++++ -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/issue-90870.rs:19:12 +error: `PartialEq` is not yet stable as a const trait + --> $DIR/issue-90870.rs:17:5 + | +LL | a == b + | ^^^^^^ + | +help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + | +LL + #![feature(const_trait_impl)] + | + +error[E0658]: cannot call conditionally-const operator in constant functions + --> $DIR/issue-90870.rs:26:12 | LL | if l == r { | ^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date help: consider dereferencing here | LL | if *l == *r { | + + -error: aborting due to 3 previous errors +error: `PartialEq` is not yet stable as a const trait + --> $DIR/issue-90870.rs:26:12 + | +LL | if l == r { + | ^^^^^^ + | +help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + | +LL + #![feature(const_trait_impl)] + | -For more information about this error, try `rustc --explain E0015`. +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/recursive-const-in-impl.stderr b/tests/ui/consts/recursive-const-in-impl.stderr index 6175112c8cc0..035d9c2f21c5 100644 --- a/tests/ui/consts/recursive-const-in-impl.stderr +++ b/tests/ui/consts/recursive-const-in-impl.stderr @@ -1,11 +1,12 @@ error: queries overflow the depth limit! - --> $DIR/recursive-const-in-impl.rs:11:14 + --> $DIR/recursive-const-in-impl.rs:11:20 | LL | println!("{}", Thing::::X); - | ^^^^ + | ^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "14"]` attribute to your crate (`recursive_const_in_impl`) = note: query depth increased by 9 when simplifying constant for the type system `main::promoted[1]` + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/defaults-well-formedness.rs b/tests/ui/defaults-well-formedness.rs deleted file mode 100644 index e5e48edad88f..000000000000 --- a/tests/ui/defaults-well-formedness.rs +++ /dev/null @@ -1,27 +0,0 @@ -//@ run-pass - -#![allow(dead_code)] -trait Trait {} -struct Foo(U, V) where U: Trait; - -trait Marker {} -struct TwoParams(T, U); -impl Marker for TwoParams {} - -// Clauses with more than 1 param are not checked. -struct IndividuallyBogus(TwoParams) where TwoParams: Marker; -struct BogusTogether(T, U) where TwoParams: Marker; -// Clauses with non-defaulted params are not checked. -struct NonDefaultedInClause(TwoParams) where TwoParams: Marker; -struct DefaultedLhs(U, V) where V: Trait; -// Dependent defaults are not checked. -struct Dependent(T, U) where U: Copy; -trait SelfBound {} -// Not even for well-formedness. -struct WellFormedProjection::Item>(A, T); - -// Issue #49344, predicates with lifetimes should not be checked. -trait Scope<'a> {} -struct Request<'a, S: Scope<'a> = i32>(S, &'a ()); - -fn main() {} diff --git a/tests/ui/deprecation/deprecated-expr-precedence.rs b/tests/ui/deprecation/deprecated-expr-precedence.rs new file mode 100644 index 000000000000..9636b46df201 --- /dev/null +++ b/tests/ui/deprecation/deprecated-expr-precedence.rs @@ -0,0 +1,8 @@ +//@ check-fail +//@ compile-flags: --crate-type=lib + +// Regression test for issue 142649 +pub fn public() { + #[deprecated] 0 + //~^ ERROR mismatched types +} diff --git a/tests/ui/deprecation/deprecated-expr-precedence.stderr b/tests/ui/deprecation/deprecated-expr-precedence.stderr new file mode 100644 index 000000000000..3275f2e790ae --- /dev/null +++ b/tests/ui/deprecation/deprecated-expr-precedence.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/deprecated-expr-precedence.rs:6:19 + | +LL | pub fn public() { + | - help: try adding a return type: `-> i32` +LL | #[deprecated] 0 + | ^ expected `()`, found integer + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/deprecation-in-force-unstable.rs b/tests/ui/deprecation/deprecated_main_function.rs similarity index 90% rename from tests/ui/deprecation-in-force-unstable.rs rename to tests/ui/deprecation/deprecated_main_function.rs index 6aaf29b069a6..398046637d80 100644 --- a/tests/ui/deprecation-in-force-unstable.rs +++ b/tests/ui/deprecation/deprecated_main_function.rs @@ -2,4 +2,4 @@ //@ compile-flags:-Zforce-unstable-if-unmarked #[deprecated] // should work even with -Zforce-unstable-if-unmarked -fn main() { } +fn main() {} diff --git a/tests/ui/deprecation/deprecated_no_stack_check.rs b/tests/ui/deprecation/deprecated_no_stack_check.rs index ef482098634a..8e1f5bbf045a 100644 --- a/tests/ui/deprecation/deprecated_no_stack_check.rs +++ b/tests/ui/deprecation/deprecated_no_stack_check.rs @@ -1,5 +1,3 @@ -//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION" - #![deny(warnings)] #![feature(no_stack_check)] //~^ ERROR: feature has been removed [E0557] diff --git a/tests/ui/deprecation/deprecated_no_stack_check.stderr b/tests/ui/deprecation/deprecated_no_stack_check.stderr index 2d08b1b8db54..33788661d730 100644 --- a/tests/ui/deprecation/deprecated_no_stack_check.stderr +++ b/tests/ui/deprecation/deprecated_no_stack_check.stderr @@ -1,10 +1,10 @@ error[E0557]: feature has been removed - --> $DIR/deprecated_no_stack_check.rs:4:12 + --> $DIR/deprecated_no_stack_check.rs:2:12 | LL | #![feature(no_stack_check)] | ^^^^^^^^^^^^^^ feature has been removed | - = note: removed in 1.0.0 (you are using $RUSTC_VERSION); see for more information + = note: removed in 1.0.0; see for more information error: aborting due to 1 previous error diff --git a/tests/ui/deref-rc.rs b/tests/ui/deref-rc.rs deleted file mode 100644 index 92fdd9003592..000000000000 --- a/tests/ui/deref-rc.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ run-pass - -use std::rc::Rc; - -fn main() { - let x = Rc::new([1, 2, 3, 4]); - assert_eq!(*x, [1, 2, 3, 4]); -} diff --git a/tests/ui/deref.rs b/tests/ui/deref.rs deleted file mode 100644 index 0a6f3cc81f6c..000000000000 --- a/tests/ui/deref.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ run-pass - -pub fn main() { - let x: Box = Box::new(10); - let _y: isize = *x; -} diff --git a/tests/ui/derive-uninhabited-enum-38885.rs b/tests/ui/derive-uninhabited-enum-38885.rs deleted file mode 100644 index 2259a542706e..000000000000 --- a/tests/ui/derive-uninhabited-enum-38885.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ check-pass -//@ compile-flags: -Wunused - -// ensure there are no special warnings about uninhabited types -// when deriving Debug on an empty enum - -#[derive(Debug)] -enum Void {} - -#[derive(Debug)] -enum Foo { - Bar(#[allow(dead_code)] u8), - Void(Void), //~ WARN variant `Void` is never constructed -} - -fn main() { - let x = Foo::Bar(42); - println!("{:?}", x); -} diff --git a/tests/ui/derives/clone-debug-dead-code.stderr b/tests/ui/derives/clone-debug-dead-code.stderr index 34b7f929ec5e..38be486e3320 100644 --- a/tests/ui/derives/clone-debug-dead-code.stderr +++ b/tests/ui/derives/clone-debug-dead-code.stderr @@ -40,7 +40,7 @@ LL | struct D { f: () } | | | field in this struct | - = note: `D` has derived impls for the traits `Debug` and `Clone`, but these are intentionally ignored during dead code analysis + = note: `D` has derived impls for the traits `Clone` and `Debug`, but these are intentionally ignored during dead code analysis error: field `f` is never read --> $DIR/clone-debug-dead-code.rs:21:12 diff --git a/tests/ui/derives/derive-debug-uninhabited-enum.rs b/tests/ui/derives/derive-debug-uninhabited-enum.rs new file mode 100644 index 000000000000..be7b3ab348d6 --- /dev/null +++ b/tests/ui/derives/derive-debug-uninhabited-enum.rs @@ -0,0 +1,23 @@ +//! Regression test for `#[derive(Debug)]` on enums with uninhabited variants. +//! +//! Ensures there are no special warnings about uninhabited types when deriving +//! Debug on an enum with uninhabited variants, only standard unused warnings. +//! +//! Issue: https://github.com/rust-lang/rust/issues/38885 + +//@ check-pass +//@ compile-flags: -Wunused + +#[derive(Debug)] +enum Void {} + +#[derive(Debug)] +enum Foo { + Bar(#[allow(dead_code)] u8), + Void(Void), //~ WARN variant `Void` is never constructed +} + +fn main() { + let x = Foo::Bar(42); + println!("{:?}", x); +} diff --git a/tests/ui/derive-uninhabited-enum-38885.stderr b/tests/ui/derives/derive-debug-uninhabited-enum.stderr similarity index 89% rename from tests/ui/derive-uninhabited-enum-38885.stderr rename to tests/ui/derives/derive-debug-uninhabited-enum.stderr index bcd8f6b7b536..4911b6b6cded 100644 --- a/tests/ui/derive-uninhabited-enum-38885.stderr +++ b/tests/ui/derives/derive-debug-uninhabited-enum.stderr @@ -1,5 +1,5 @@ warning: variant `Void` is never constructed - --> $DIR/derive-uninhabited-enum-38885.rs:13:5 + --> $DIR/derive-debug-uninhabited-enum.rs:17:5 | LL | enum Foo { | --- variant in this enum diff --git a/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr index a7f6d094681a..147910b715f5 100644 --- a/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr @@ -5,9 +5,8 @@ LL | #[derive(Debug)] | ----- in this derive macro expansion ... LL | x: Error - | ^^^^^^^^ `Error` cannot be formatted using `{:?}` + | ^^^^^^^^ the trait `Debug` is not implemented for `Error` | - = help: the trait `Debug` is not implemented for `Error` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` help: consider annotating `Error` with `#[derive(Debug)]` | diff --git a/tests/ui/derives/derives-span-Debug-enum.stderr b/tests/ui/derives/derives-span-Debug-enum.stderr index b3a584781598..6f97ceb02d3a 100644 --- a/tests/ui/derives/derives-span-Debug-enum.stderr +++ b/tests/ui/derives/derives-span-Debug-enum.stderr @@ -5,9 +5,8 @@ LL | #[derive(Debug)] | ----- in this derive macro expansion ... LL | Error - | ^^^^^ `Error` cannot be formatted using `{:?}` + | ^^^^^ the trait `Debug` is not implemented for `Error` | - = help: the trait `Debug` is not implemented for `Error` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` help: consider annotating `Error` with `#[derive(Debug)]` | diff --git a/tests/ui/derives/derives-span-Debug-struct.stderr b/tests/ui/derives/derives-span-Debug-struct.stderr index c8ad652716ca..46d69a892f25 100644 --- a/tests/ui/derives/derives-span-Debug-struct.stderr +++ b/tests/ui/derives/derives-span-Debug-struct.stderr @@ -5,9 +5,8 @@ LL | #[derive(Debug)] | ----- in this derive macro expansion LL | struct Struct { LL | x: Error - | ^^^^^^^^ `Error` cannot be formatted using `{:?}` + | ^^^^^^^^ the trait `Debug` is not implemented for `Error` | - = help: the trait `Debug` is not implemented for `Error` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` help: consider annotating `Error` with `#[derive(Debug)]` | diff --git a/tests/ui/derives/derives-span-Debug-tuple-struct.stderr b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr index dbece4d2091b..a3feeff6df37 100644 --- a/tests/ui/derives/derives-span-Debug-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr @@ -5,9 +5,8 @@ LL | #[derive(Debug)] | ----- in this derive macro expansion LL | struct Struct( LL | Error - | ^^^^^ `Error` cannot be formatted using `{:?}` + | ^^^^^ the trait `Debug` is not implemented for `Error` | - = help: the trait `Debug` is not implemented for `Error` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` help: consider annotating `Error` with `#[derive(Debug)]` | diff --git a/tests/ui/derives/nonsense-input-to-debug.rs b/tests/ui/derives/nonsense-input-to-debug.rs new file mode 100644 index 000000000000..7dfa3cd616a7 --- /dev/null +++ b/tests/ui/derives/nonsense-input-to-debug.rs @@ -0,0 +1,12 @@ +// Issue: #32950 +// Ensure that using macros rather than a type doesn't break `derive`. + +#[derive(Debug)] +struct Nonsense { + //~^ ERROR type parameter `T` is never used + should_be_vec_t: vec![T], + //~^ ERROR `derive` cannot be used on items with type macros + //~| ERROR expected type, found `expr` metavariable +} + +fn main() {} diff --git a/tests/ui/derives/nonsense-input-to-debug.stderr b/tests/ui/derives/nonsense-input-to-debug.stderr new file mode 100644 index 000000000000..7c97ca93cfc9 --- /dev/null +++ b/tests/ui/derives/nonsense-input-to-debug.stderr @@ -0,0 +1,30 @@ +error: `derive` cannot be used on items with type macros + --> $DIR/nonsense-input-to-debug.rs:7:22 + | +LL | should_be_vec_t: vec![T], + | ^^^^^^^ + +error: expected type, found `expr` metavariable + --> $DIR/nonsense-input-to-debug.rs:7:22 + | +LL | should_be_vec_t: vec![T], + | ^^^^^^^ + | | + | expected type + | in this macro invocation + | this macro call doesn't expand to a type + | + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0392]: type parameter `T` is never used + --> $DIR/nonsense-input-to-debug.rs:5:17 + | +LL | struct Nonsense { + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/destructure-trait-ref.rs b/tests/ui/destructure-trait-ref.rs deleted file mode 100644 index daa0ca30d687..000000000000 --- a/tests/ui/destructure-trait-ref.rs +++ /dev/null @@ -1,46 +0,0 @@ -// The regression test for #15031 to make sure destructuring trait -// reference work properly. - -//@ dont-require-annotations: NOTE - -#![feature(box_patterns)] - -trait T { fn foo(&self) {} } -impl T for isize {} - - -fn main() { - // For an expression of the form: - // - // let &...&x = &..&SomeTrait; - // - // Say we have n `&` at the left hand and m `&` right hand, then: - // if n < m, we are golden; - // if n == m, it's a derefing non-derefable type error; - // if n > m, it's a type mismatch error. - - // n < m - let &x = &(&1isize as &dyn T); - let &x = &&(&1isize as &dyn T); - let &&x = &&(&1isize as &dyn T); - - // n == m - let &x = &1isize as &dyn T; //~ ERROR type `&dyn T` cannot be dereferenced - let &&x = &(&1isize as &dyn T); //~ ERROR type `&dyn T` cannot be dereferenced - let box x = Box::new(1isize) as Box; - //~^ ERROR type `Box` cannot be dereferenced - - // n > m - let &&x = &1isize as &dyn T; - //~^ ERROR mismatched types - //~| NOTE expected trait object `dyn T` - //~| NOTE found reference `&_` - let &&&x = &(&1isize as &dyn T); - //~^ ERROR mismatched types - //~| NOTE expected trait object `dyn T` - //~| NOTE found reference `&_` - let box box x = Box::new(1isize) as Box; - //~^ ERROR mismatched types - //~| NOTE expected trait object `dyn T` - //~| NOTE found struct `Box<_>` -} diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr index 5408825d8cd6..18d80810ab0c 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr @@ -1,7 +1,7 @@ error[E0308]: mismatched types --> $DIR/non-whitespace-trimming-unicode.rs:4:415 | -LL | ...♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼... +LL | ...♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽ ... | -- ^^ expected `()`, found integer | | | expected due to this diff --git a/tests/ui/diverging-fallback-method-chain.rs b/tests/ui/diverging-fallback-method-chain.rs deleted file mode 100644 index aa8eba1191b9..000000000000 --- a/tests/ui/diverging-fallback-method-chain.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ run-pass - -#![allow(unused_imports)] -// Test a regression found when building compiler. The `produce()` -// error type `T` winds up getting unified with result of `x.parse()`; -// the type of the closure given to `unwrap_or_else` needs to be -// inferred to `usize`. - -use std::num::ParseIntError; - -fn produce() -> Result<&'static str, T> { - Ok("22") -} - -fn main() { - let x: usize = produce() - .and_then(|x| x.parse()) - .unwrap_or_else(|_| panic!()); - println!("{}", x); -} diff --git a/tests/ui/diverging-fallback-option.rs b/tests/ui/diverging-fallback-option.rs deleted file mode 100644 index aa793ebd0178..000000000000 --- a/tests/ui/diverging-fallback-option.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ run-pass - -#![allow(warnings)] - -// Here the type of `c` is `Option`, where `?T` is unconstrained. -// Because there is data-flow from the `{ return; }` block, which -// diverges and hence has type `!`, into `c`, we will default `?T` to -// `!`, and hence this code compiles rather than failing and requiring -// a type annotation. - -fn main() { - let c = Some({ return; }); - c.unwrap(); -} diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr index d8935be56094..8b4f3f52ee93 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr @@ -87,6 +87,11 @@ help: alternatively, consider constraining `g` so it does not apply to trait obj | LL | trait A { fn g(b: B) -> B where Self: Sized; } | +++++++++++++++++ +help: you might have meant to use `Self` to refer to the implementing type + | +LL - trait B { fn f(a: A) -> A; } +LL + trait B { fn f(a: Self) -> A; } + | warning: trait objects without an explicit `dyn` are deprecated --> $DIR/avoid-ice-on-warning-3.rs:14:19 @@ -124,6 +129,11 @@ help: alternatively, consider constraining `f` so it does not apply to trait obj | LL | trait B { fn f(a: A) -> A where Self: Sized; } | +++++++++++++++++ +help: you might have meant to use `Self` to refer to the implementing type + | +LL - trait A { fn g(b: B) -> B; } +LL + trait A { fn g(b: Self) -> B; } + | error: aborting due to 2 previous errors; 6 warnings emitted diff --git a/tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs index 9e5c1bfe4160..b866dab9dba2 100644 --- a/tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs +++ b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs @@ -8,8 +8,7 @@ trait GatTrait { trait SuperTrait: for<'a> GatTrait = T> { fn c(&self) -> dyn SuperTrait; - //~^ ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `SuperTrait` is not dyn compatible + //~^ ERROR the trait `SuperTrait` is not dyn compatible } fn main() {} diff --git a/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr index 582cf1af0546..ba4ce4753995 100644 --- a/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr +++ b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr @@ -7,20 +7,6 @@ LL | Self: 'a; | ^^ = help: consider adding an explicit lifetime bound `Self: 'a`... -error: associated item referring to unboxed trait object for its own trait - --> $DIR/supertrait-mentions-GAT.rs:10:20 - | -LL | trait SuperTrait: for<'a> GatTrait = T> { - | ---------- in this trait -LL | fn c(&self) -> dyn SuperTrait; - | ^^^^^^^^^^^^^^^^^ - | -help: you might have meant to use `Self` to refer to the implementing type - | -LL - fn c(&self) -> dyn SuperTrait; -LL + fn c(&self) -> Self; - | - error[E0038]: the trait `SuperTrait` is not dyn compatible --> $DIR/supertrait-mentions-GAT.rs:10:20 | @@ -37,8 +23,13 @@ LL | type Gat<'a> LL | trait SuperTrait: for<'a> GatTrait = T> { | ---------- this trait is not dyn compatible... = help: consider moving `Gat` to another trait +help: you might have meant to use `Self` to refer to the implementing type + | +LL - fn c(&self) -> dyn SuperTrait; +LL + fn c(&self) -> Self; + | -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0038, E0311. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.not-diag-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.not-diag-in-deps.stderr index 3ddff11798de..229bfbe59e50 100644 --- a/tests/ui/errors/remap-path-prefix-diagnostics.not-diag-in-deps.stderr +++ b/tests/ui/errors/remap-path-prefix-diagnostics.not-diag-in-deps.stderr @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display` --> remapped/errors/remap-path-prefix-diagnostics.rs:LL:COL | LL | impl r#trait::Trait for A {} - | ^ `A` cannot be formatted with the default formatter + | ^ the trait `std::fmt::Display` is not implemented for `A` | - = help: the trait `std::fmt::Display` is not implemented for `A` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `Trait` --> $DIR/auxiliary/trait.rs:LL:COL | diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.only-debuginfo-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.only-debuginfo-in-deps.stderr index 85c781425b16..a59af3b6a826 100644 --- a/tests/ui/errors/remap-path-prefix-diagnostics.only-debuginfo-in-deps.stderr +++ b/tests/ui/errors/remap-path-prefix-diagnostics.only-debuginfo-in-deps.stderr @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display` --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL | LL | impl r#trait::Trait for A {} - | ^ `A` cannot be formatted with the default formatter + | ^ the trait `std::fmt::Display` is not implemented for `A` | - = help: the trait `std::fmt::Display` is not implemented for `A` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `Trait` --> $DIR/auxiliary/trait-debuginfo.rs:LL:COL | diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.only-diag-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.only-diag-in-deps.stderr index 792ea7925ad5..18fb9afcf390 100644 --- a/tests/ui/errors/remap-path-prefix-diagnostics.only-diag-in-deps.stderr +++ b/tests/ui/errors/remap-path-prefix-diagnostics.only-diag-in-deps.stderr @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display` --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL | LL | impl r#trait::Trait for A {} - | ^ `A` cannot be formatted with the default formatter + | ^ the trait `std::fmt::Display` is not implemented for `A` | - = help: the trait `std::fmt::Display` is not implemented for `A` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `Trait` --> $DIR/auxiliary/trait-diag.rs:LL:COL | diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.only-macro-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.only-macro-in-deps.stderr index d13333d2e482..9e770f07fba2 100644 --- a/tests/ui/errors/remap-path-prefix-diagnostics.only-macro-in-deps.stderr +++ b/tests/ui/errors/remap-path-prefix-diagnostics.only-macro-in-deps.stderr @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display` --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL | LL | impl r#trait::Trait for A {} - | ^ `A` cannot be formatted with the default formatter + | ^ the trait `std::fmt::Display` is not implemented for `A` | - = help: the trait `std::fmt::Display` is not implemented for `A` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `Trait` --> $DIR/auxiliary/trait-macro.rs:LL:COL | diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.with-debuginfo-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.with-debuginfo-in-deps.stderr index 85c781425b16..a59af3b6a826 100644 --- a/tests/ui/errors/remap-path-prefix-diagnostics.with-debuginfo-in-deps.stderr +++ b/tests/ui/errors/remap-path-prefix-diagnostics.with-debuginfo-in-deps.stderr @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display` --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL | LL | impl r#trait::Trait for A {} - | ^ `A` cannot be formatted with the default formatter + | ^ the trait `std::fmt::Display` is not implemented for `A` | - = help: the trait `std::fmt::Display` is not implemented for `A` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `Trait` --> $DIR/auxiliary/trait-debuginfo.rs:LL:COL | diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.with-diag-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.with-diag-in-deps.stderr index 08f7fb2c7364..ca6f2b1697a8 100644 --- a/tests/ui/errors/remap-path-prefix-diagnostics.with-diag-in-deps.stderr +++ b/tests/ui/errors/remap-path-prefix-diagnostics.with-diag-in-deps.stderr @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display` --> remapped/errors/remap-path-prefix-diagnostics.rs:LL:COL | LL | impl r#trait::Trait for A {} - | ^ `A` cannot be formatted with the default formatter + | ^ the trait `std::fmt::Display` is not implemented for `A` | - = help: the trait `std::fmt::Display` is not implemented for `A` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `Trait` --> remapped/errors/auxiliary/trait-diag.rs:LL:COL | diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.with-macro-in-deps.stderr b/tests/ui/errors/remap-path-prefix-diagnostics.with-macro-in-deps.stderr index d13333d2e482..9e770f07fba2 100644 --- a/tests/ui/errors/remap-path-prefix-diagnostics.with-macro-in-deps.stderr +++ b/tests/ui/errors/remap-path-prefix-diagnostics.with-macro-in-deps.stderr @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display` --> $DIR/remap-path-prefix-diagnostics.rs:LL:COL | LL | impl r#trait::Trait for A {} - | ^ `A` cannot be formatted with the default formatter + | ^ the trait `std::fmt::Display` is not implemented for `A` | - = help: the trait `std::fmt::Display` is not implemented for `A` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `Trait` --> $DIR/auxiliary/trait-macro.rs:LL:COL | diff --git a/tests/ui/extern-flag/auxiliary/panic_handler.rs b/tests/ui/extern-flag/auxiliary/panic_handler.rs index 9140ceed2291..9607f0ed0139 100644 --- a/tests/ui/extern-flag/auxiliary/panic_handler.rs +++ b/tests/ui/extern-flag/auxiliary/panic_handler.rs @@ -12,4 +12,12 @@ pub fn begin_panic_handler(_info: &core::panic::PanicInfo<'_>) -> ! { } #[lang = "eh_personality"] -extern "C" fn eh_personality() {} +extern "C" fn eh_personality( + _version: i32, + _actions: i32, + _exception_class: u64, + _exception_object: *mut (), + _context: *mut (), +) -> i32 { + loop {} +} diff --git a/tests/ui/feature-gates/feature-gate-abi-custom.rs b/tests/ui/feature-gates/feature-gate-abi-custom.rs index 3ddce974dd7d..312b6230b743 100644 --- a/tests/ui/feature-gates/feature-gate-abi-custom.rs +++ b/tests/ui/feature-gates/feature-gate-abi-custom.rs @@ -15,11 +15,11 @@ unsafe extern "custom" fn f7() { trait Tr { extern "custom" fn m7(); //~^ ERROR "custom" ABI is experimental - //~| ERROR functions with the `"custom"` ABI must be unsafe + //~| ERROR functions with the "custom" ABI must be unsafe #[unsafe(naked)] extern "custom" fn dm7() { //~^ ERROR "custom" ABI is experimental - //~| ERROR functions with the `"custom"` ABI must be unsafe + //~| ERROR functions with the "custom" ABI must be unsafe naked_asm!("") } } @@ -31,7 +31,7 @@ impl Tr for S { #[unsafe(naked)] extern "custom" fn m7() { //~^ ERROR "custom" ABI is experimental - //~| ERROR functions with the `"custom"` ABI must be unsafe + //~| ERROR functions with the "custom" ABI must be unsafe naked_asm!("") } } @@ -41,7 +41,7 @@ impl S { #[unsafe(naked)] extern "custom" fn im7() { //~^ ERROR "custom" ABI is experimental - //~| ERROR functions with the `"custom"` ABI must be unsafe + //~| ERROR functions with the "custom" ABI must be unsafe naked_asm!("") } } diff --git a/tests/ui/feature-gates/feature-gate-abi-custom.stderr b/tests/ui/feature-gates/feature-gate-abi-custom.stderr index e6dce0126d64..e359dbb5ebe1 100644 --- a/tests/ui/feature-gates/feature-gate-abi-custom.stderr +++ b/tests/ui/feature-gates/feature-gate-abi-custom.stderr @@ -1,4 +1,4 @@ -error: functions with the `"custom"` ABI must be unsafe +error: functions with the "custom" ABI must be unsafe --> $DIR/feature-gate-abi-custom.rs:16:5 | LL | extern "custom" fn m7(); @@ -9,7 +9,7 @@ help: add the `unsafe` keyword to this definition LL | unsafe extern "custom" fn m7(); | ++++++ -error: functions with the `"custom"` ABI must be unsafe +error: functions with the "custom" ABI must be unsafe --> $DIR/feature-gate-abi-custom.rs:20:5 | LL | extern "custom" fn dm7() { @@ -20,7 +20,7 @@ help: add the `unsafe` keyword to this definition LL | unsafe extern "custom" fn dm7() { | ++++++ -error: functions with the `"custom"` ABI must be unsafe +error: functions with the "custom" ABI must be unsafe --> $DIR/feature-gate-abi-custom.rs:32:5 | LL | extern "custom" fn m7() { @@ -31,7 +31,7 @@ help: add the `unsafe` keyword to this definition LL | unsafe extern "custom" fn m7() { | ++++++ -error: functions with the `"custom"` ABI must be unsafe +error: functions with the "custom" ABI must be unsafe --> $DIR/feature-gate-abi-custom.rs:42:5 | LL | extern "custom" fn im7() { diff --git a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.AMDGPU.stderr b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.AMDGPU.stderr index fca32c5c1e6f..4fa3fee942ea 100644 --- a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.AMDGPU.stderr +++ b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.AMDGPU.stderr @@ -19,7 +19,7 @@ LL | extern "gpu-kernel" fn m1(_: ()); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:23:12 + --> $DIR/feature-gate-abi_gpu_kernel.rs:24:12 | LL | extern "gpu-kernel" fn dm1(_: ()) {} | ^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | extern "gpu-kernel" fn dm1(_: ()) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:31:12 + --> $DIR/feature-gate-abi_gpu_kernel.rs:32:12 | LL | extern "gpu-kernel" fn m1(_: ()) {} | ^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | extern "gpu-kernel" fn m1(_: ()) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:37:12 + --> $DIR/feature-gate-abi_gpu_kernel.rs:38:12 | LL | extern "gpu-kernel" fn im1(_: ()) {} | ^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | extern "gpu-kernel" fn im1(_: ()) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:42:18 + --> $DIR/feature-gate-abi_gpu_kernel.rs:43:18 | LL | type A1 = extern "gpu-kernel" fn(_: ()); | ^^^^^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.HOST.stderr b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.HOST.stderr index cc81289f6b78..88734bc9d225 100644 --- a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.HOST.stderr +++ b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.HOST.stderr @@ -1,3 +1,9 @@ +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/feature-gate-abi_gpu_kernel.rs:16:8 + | +LL | extern "gpu-kernel" fn f1(_: ()) {} + | ^^^^^^^^^^^^ + error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change --> $DIR/feature-gate-abi_gpu_kernel.rs:16:8 | @@ -8,6 +14,12 @@ LL | extern "gpu-kernel" fn f1(_: ()) {} = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/feature-gate-abi_gpu_kernel.rs:21:12 + | +LL | extern "gpu-kernel" fn m1(_: ()); + | ^^^^^^^^^^^^ + error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change --> $DIR/feature-gate-abi_gpu_kernel.rs:21:12 | @@ -18,8 +30,14 @@ LL | extern "gpu-kernel" fn m1(_: ()); = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/feature-gate-abi_gpu_kernel.rs:24:12 + | +LL | extern "gpu-kernel" fn dm1(_: ()) {} + | ^^^^^^^^^^^^ + error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:23:12 + --> $DIR/feature-gate-abi_gpu_kernel.rs:24:12 | LL | extern "gpu-kernel" fn dm1(_: ()) {} | ^^^^^^^^^^^^ @@ -28,8 +46,14 @@ LL | extern "gpu-kernel" fn dm1(_: ()) {} = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/feature-gate-abi_gpu_kernel.rs:32:12 + | +LL | extern "gpu-kernel" fn m1(_: ()) {} + | ^^^^^^^^^^^^ + error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:31:12 + --> $DIR/feature-gate-abi_gpu_kernel.rs:32:12 | LL | extern "gpu-kernel" fn m1(_: ()) {} | ^^^^^^^^^^^^ @@ -38,8 +62,14 @@ LL | extern "gpu-kernel" fn m1(_: ()) {} = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/feature-gate-abi_gpu_kernel.rs:38:12 + | +LL | extern "gpu-kernel" fn im1(_: ()) {} + | ^^^^^^^^^^^^ + error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:37:12 + --> $DIR/feature-gate-abi_gpu_kernel.rs:38:12 | LL | extern "gpu-kernel" fn im1(_: ()) {} | ^^^^^^^^^^^^ @@ -48,8 +78,14 @@ LL | extern "gpu-kernel" fn im1(_: ()) {} = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/feature-gate-abi_gpu_kernel.rs:43:18 + | +LL | type A1 = extern "gpu-kernel" fn(_: ()); + | ^^^^^^^^^^^^ + error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:42:18 + --> $DIR/feature-gate-abi_gpu_kernel.rs:43:18 | LL | type A1 = extern "gpu-kernel" fn(_: ()); | ^^^^^^^^^^^^ @@ -58,6 +94,12 @@ LL | type A1 = extern "gpu-kernel" fn(_: ()); = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0570]: "gpu-kernel" is not a supported ABI for the current target + --> $DIR/feature-gate-abi_gpu_kernel.rs:47:8 + | +LL | extern "gpu-kernel" {} + | ^^^^^^^^^^^^ + error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change --> $DIR/feature-gate-abi_gpu_kernel.rs:47:8 | @@ -68,58 +110,7 @@ LL | extern "gpu-kernel" {} = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -warning: the calling convention "gpu-kernel" is not supported on this target - --> $DIR/feature-gate-abi_gpu_kernel.rs:42:11 - | -LL | type A1 = extern "gpu-kernel" fn(_: ()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - -error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_gpu_kernel.rs:47:1 - | -LL | extern "gpu-kernel" {} - | ^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_gpu_kernel.rs:16:1 - | -LL | extern "gpu-kernel" fn f1(_: ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_gpu_kernel.rs:23:5 - | -LL | extern "gpu-kernel" fn dm1(_: ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_gpu_kernel.rs:31:5 - | -LL | extern "gpu-kernel" fn m1(_: ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_gpu_kernel.rs:37:5 - | -LL | extern "gpu-kernel" fn im1(_: ()) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 12 previous errors; 1 warning emitted +error: aborting due to 14 previous errors Some errors have detailed explanations: E0570, E0658. For more information about an error, try `rustc --explain E0570`. -Future incompatibility report: Future breakage diagnostic: -warning: the calling convention "gpu-kernel" is not supported on this target - --> $DIR/feature-gate-abi_gpu_kernel.rs:42:11 - | -LL | type A1 = extern "gpu-kernel" fn(_: ()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #130260 - = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default - diff --git a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.NVPTX.stderr b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.NVPTX.stderr index fca32c5c1e6f..4fa3fee942ea 100644 --- a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.NVPTX.stderr +++ b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.NVPTX.stderr @@ -19,7 +19,7 @@ LL | extern "gpu-kernel" fn m1(_: ()); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:23:12 + --> $DIR/feature-gate-abi_gpu_kernel.rs:24:12 | LL | extern "gpu-kernel" fn dm1(_: ()) {} | ^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | extern "gpu-kernel" fn dm1(_: ()) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:31:12 + --> $DIR/feature-gate-abi_gpu_kernel.rs:32:12 | LL | extern "gpu-kernel" fn m1(_: ()) {} | ^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | extern "gpu-kernel" fn m1(_: ()) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:37:12 + --> $DIR/feature-gate-abi_gpu_kernel.rs:38:12 | LL | extern "gpu-kernel" fn im1(_: ()) {} | ^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | extern "gpu-kernel" fn im1(_: ()) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:42:18 + --> $DIR/feature-gate-abi_gpu_kernel.rs:43:18 | LL | type A1 = extern "gpu-kernel" fn(_: ()); | ^^^^^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.rs b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.rs index 7b1ee681dd7e..988fbd83afcc 100644 --- a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.rs +++ b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.rs @@ -19,6 +19,7 @@ extern "gpu-kernel" fn f1(_: ()) {} //~ ERROR "gpu-kernel" ABI is experimental a // Methods in trait definition trait Tr { extern "gpu-kernel" fn m1(_: ()); //~ ERROR "gpu-kernel" ABI is experimental and subject to change + //[HOST]~^ ERROR is not a supported ABI extern "gpu-kernel" fn dm1(_: ()) {} //~ ERROR "gpu-kernel" ABI is experimental and subject to change //[HOST]~^ ERROR is not a supported ABI @@ -40,8 +41,7 @@ impl S { // Function pointer types type A1 = extern "gpu-kernel" fn(_: ()); //~ ERROR "gpu-kernel" ABI is experimental and subject to change -//[HOST]~^ WARNING the calling convention "gpu-kernel" is not supported on this target [unsupported_fn_ptr_calling_conventions] -//[HOST]~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +//[HOST]~^ ERROR is not a supported ABI // Foreign modules extern "gpu-kernel" {} //~ ERROR "gpu-kernel" ABI is experimental and subject to change diff --git a/tests/ui/feature-gates/feature-gate-cfi_encoding.rs b/tests/ui/feature-gates/feature-gate-cfi_encoding.rs index 3cef8156014b..b6312dd7817f 100644 --- a/tests/ui/feature-gates/feature-gate-cfi_encoding.rs +++ b/tests/ui/feature-gates/feature-gate-cfi_encoding.rs @@ -1,4 +1,4 @@ #![crate_type = "lib"] -#[cfi_encoding = "3Bar"] //~ERROR 3:1: 3:25: the `#[cfi_encoding]` attribute is an experimental feature [E0658] +#[cfi_encoding = "3Bar"] //~ ERROR the `#[cfi_encoding]` attribute is an experimental feature [E0658] pub struct Foo(i32); diff --git a/tests/ui/feature-gates/feature-gate-concat_idents.rs b/tests/ui/feature-gates/feature-gate-concat_idents.rs deleted file mode 100644 index 4fc3b6915973..000000000000 --- a/tests/ui/feature-gates/feature-gate-concat_idents.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![expect(deprecated)] // concat_idents is deprecated - -const XY_1: i32 = 10; - -fn main() { - const XY_2: i32 = 20; - let a = concat_idents!(X, Y_1); //~ ERROR `concat_idents` is not stable - let b = concat_idents!(X, Y_2); //~ ERROR `concat_idents` is not stable - assert_eq!(a, 10); - assert_eq!(b, 20); -} diff --git a/tests/ui/feature-gates/feature-gate-concat_idents.stderr b/tests/ui/feature-gates/feature-gate-concat_idents.stderr deleted file mode 100644 index 6399424eecd8..000000000000 --- a/tests/ui/feature-gates/feature-gate-concat_idents.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change - --> $DIR/feature-gate-concat_idents.rs:7:13 - | -LL | let a = concat_idents!(X, Y_1); - | ^^^^^^^^^^^^^ - | - = note: see issue #29599 for more information - = help: add `#![feature(concat_idents)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change - --> $DIR/feature-gate-concat_idents.rs:8:13 - | -LL | let b = concat_idents!(X, Y_2); - | ^^^^^^^^^^^^^ - | - = note: see issue #29599 for more information - = help: add `#![feature(concat_idents)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-concat_idents2.rs b/tests/ui/feature-gates/feature-gate-concat_idents2.rs deleted file mode 100644 index bc2b4f7cddf9..000000000000 --- a/tests/ui/feature-gates/feature-gate-concat_idents2.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![expect(deprecated)] // concat_idents is deprecated - -fn main() { - concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough - //~| ERROR cannot find value `ab` in this scope -} diff --git a/tests/ui/feature-gates/feature-gate-concat_idents2.stderr b/tests/ui/feature-gates/feature-gate-concat_idents2.stderr deleted file mode 100644 index a770c1a348b5..000000000000 --- a/tests/ui/feature-gates/feature-gate-concat_idents2.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change - --> $DIR/feature-gate-concat_idents2.rs:4:5 - | -LL | concat_idents!(a, b); - | ^^^^^^^^^^^^^ - | - = note: see issue #29599 for more information - = help: add `#![feature(concat_idents)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0425]: cannot find value `ab` in this scope - --> $DIR/feature-gate-concat_idents2.rs:4:5 - | -LL | concat_idents!(a, b); - | ^^^^^^^^^^^^^^^^^^^^ not found in this scope - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0425, E0658. -For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/feature-gates/feature-gate-concat_idents3.rs b/tests/ui/feature-gates/feature-gate-concat_idents3.rs deleted file mode 100644 index d4a0d2e6bb0e..000000000000 --- a/tests/ui/feature-gates/feature-gate-concat_idents3.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![expect(deprecated)] // concat_idents is deprecated - -const XY_1: i32 = 10; - -fn main() { - const XY_2: i32 = 20; - assert_eq!(10, concat_idents!(X, Y_1)); //~ ERROR `concat_idents` is not stable - assert_eq!(20, concat_idents!(X, Y_2)); //~ ERROR `concat_idents` is not stable -} diff --git a/tests/ui/feature-gates/feature-gate-concat_idents3.stderr b/tests/ui/feature-gates/feature-gate-concat_idents3.stderr deleted file mode 100644 index 7d929322bc06..000000000000 --- a/tests/ui/feature-gates/feature-gate-concat_idents3.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change - --> $DIR/feature-gate-concat_idents3.rs:7:20 - | -LL | assert_eq!(10, concat_idents!(X, Y_1)); - | ^^^^^^^^^^^^^ - | - = note: see issue #29599 for more information - = help: add `#![feature(concat_idents)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change - --> $DIR/feature-gate-concat_idents3.rs:8:20 - | -LL | assert_eq!(20, concat_idents!(X, Y_2)); - | ^^^^^^^^^^^^^ - | - = note: see issue #29599 for more information - = help: add `#![feature(concat_idents)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-coverage-attribute.rs b/tests/ui/feature-gates/feature-gate-coverage-attribute.rs index 2cf4b76180e1..0a463755f137 100644 --- a/tests/ui/feature-gates/feature-gate-coverage-attribute.rs +++ b/tests/ui/feature-gates/feature-gate-coverage-attribute.rs @@ -1,5 +1,3 @@ -//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION" - #![crate_type = "lib"] #![feature(no_coverage)] //~ ERROR feature has been removed [E0557] diff --git a/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr b/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr index 8c23544698d0..68d0d9bc3c31 100644 --- a/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr +++ b/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr @@ -1,14 +1,14 @@ error[E0557]: feature has been removed - --> $DIR/feature-gate-coverage-attribute.rs:4:12 + --> $DIR/feature-gate-coverage-attribute.rs:2:12 | LL | #![feature(no_coverage)] | ^^^^^^^^^^^ feature has been removed | - = note: removed in 1.74.0 (you are using $RUSTC_VERSION); see for more information + = note: removed in 1.74.0; see for more information = note: renamed to `coverage_attribute` error[E0658]: the `#[coverage]` attribute is an experimental feature - --> $DIR/feature-gate-coverage-attribute.rs:12:1 + --> $DIR/feature-gate-coverage-attribute.rs:10:1 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-fn_align.rs b/tests/ui/feature-gates/feature-gate-fn_align.rs index 744877704dd1..b6c300e5cbe6 100644 --- a/tests/ui/feature-gates/feature-gate-fn_align.rs +++ b/tests/ui/feature-gates/feature-gate-fn_align.rs @@ -1,9 +1,12 @@ #![crate_type = "lib"] -#[repr(align(16))] //~ ERROR `repr(align)` attributes on functions are unstable +#[align(16)] +//~^ ERROR the `#[align]` attribute is an experimental feature fn requires_alignment() {} trait MyTrait { - #[repr(align)] //~ ERROR invalid `repr(align)` attribute: `align` needs an argument + #[align] + //~^ ERROR the `#[align]` attribute is an experimental feature + //~| ERROR malformed `align` attribute input fn myfun(); } diff --git a/tests/ui/feature-gates/feature-gate-fn_align.stderr b/tests/ui/feature-gates/feature-gate-fn_align.stderr index ff17c29fe029..921cf08435c2 100644 --- a/tests/ui/feature-gates/feature-gate-fn_align.stderr +++ b/tests/ui/feature-gates/feature-gate-fn_align.stderr @@ -1,20 +1,33 @@ -error[E0589]: invalid `repr(align)` attribute: `align` needs an argument - --> $DIR/feature-gate-fn_align.rs:7:12 +error[E0658]: the `#[align]` attribute is an experimental feature + --> $DIR/feature-gate-fn_align.rs:3:1 | -LL | #[repr(align)] - | ^^^^^ help: supply an argument here: `align(...)` - -error[E0658]: `repr(align)` attributes on functions are unstable - --> $DIR/feature-gate-fn_align.rs:3:8 - | -LL | #[repr(align(16))] - | ^^^^^^^^^ +LL | #[align(16)] + | ^^^^^^^^^^^^ | = note: see issue #82232 for more information = help: add `#![feature(fn_align)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error[E0658]: the `#[align]` attribute is an experimental feature + --> $DIR/feature-gate-fn_align.rs:8:5 + | +LL | #[align] + | ^^^^^^^^ + | + = note: see issue #82232 for more information + = help: add `#![feature(fn_align)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -Some errors have detailed explanations: E0589, E0658. -For more information about an error, try `rustc --explain E0589`. +error[E0539]: malformed `align` attribute input + --> $DIR/feature-gate-fn_align.rs:8:5 + | +LL | #[align] + | ^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[align()]` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0539, E0658. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/feature-gates/feature-gate-loop-match.rs b/tests/ui/feature-gates/feature-gate-loop-match.rs new file mode 100644 index 000000000000..399b20234f32 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-loop-match.rs @@ -0,0 +1,30 @@ +// Test that `#[loop_match]` and `#[const_continue]` cannot be used without +// `#![feature(loop_match)]`. + +enum State { + A, + B, + C, +} + +fn main() { + let mut state = State::A; + #[loop_match] //~ ERROR the `#[loop_match]` attribute is an experimental feature + 'a: loop { + state = 'blk: { + match state { + State::A => { + #[const_continue] + //~^ ERROR the `#[const_continue]` attribute is an experimental feature + break 'blk State::B; + } + State::B => { + #[const_continue] + //~^ ERROR the `#[const_continue]` attribute is an experimental feature + break 'blk State::C; + } + State::C => break 'a, + } + }; + } +} diff --git a/tests/ui/feature-gates/feature-gate-loop-match.stderr b/tests/ui/feature-gates/feature-gate-loop-match.stderr new file mode 100644 index 000000000000..9b12047cf4dd --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-loop-match.stderr @@ -0,0 +1,33 @@ +error[E0658]: the `#[loop_match]` attribute is an experimental feature + --> $DIR/feature-gate-loop-match.rs:12:5 + | +LL | #[loop_match] + | ^^^^^^^^^^^^^ + | + = note: see issue #132306 for more information + = help: add `#![feature(loop_match)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the `#[const_continue]` attribute is an experimental feature + --> $DIR/feature-gate-loop-match.rs:17:21 + | +LL | #[const_continue] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #132306 for more information + = help: add `#![feature(loop_match)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the `#[const_continue]` attribute is an experimental feature + --> $DIR/feature-gate-loop-match.rs:22:21 + | +LL | #[const_continue] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #132306 for more information + = help: add `#![feature(loop_match)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr index 8e601a14753b..e57ec9cc59b2 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr +++ b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr @@ -1,8 +1,8 @@ error[E0658]: `#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions - --> $DIR/feature-gate-naked_functions_target_feature.rs:7:1 + --> $DIR/feature-gate-naked_functions_target_feature.rs:7:3 | LL | #[target_feature(enable = "avx2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = note: see issue #138568 for more information = help: add `#![feature(naked_functions_target_feature)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.rs b/tests/ui/feature-gates/feature-gate-optimize_attribute.rs index 77cc307c9f45..ed5a11270f83 100644 --- a/tests/ui/feature-gates/feature-gate-optimize_attribute.rs +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.rs @@ -11,5 +11,5 @@ fn none() {} #[optimize(banana)] //~^ ERROR the `#[optimize]` attribute is an experimental feature -//~| ERROR E0722 +//~| ERROR malformed `optimize` attribute input [E0539] fn not_known() {} diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr index 4e6e4ac2703a..e7e62b4f9899 100644 --- a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr @@ -38,13 +38,16 @@ LL | #[optimize(banana)] = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0722]: invalid argument - --> $DIR/feature-gate-optimize_attribute.rs:12:12 +error[E0539]: malformed `optimize` attribute input + --> $DIR/feature-gate-optimize_attribute.rs:12:1 | LL | #[optimize(banana)] - | ^^^^^^ + | ^^^^^^^^^^^------^^ + | | | + | | valid arguments are `size`, `speed` or `none` + | help: must be of the form: `#[optimize(size|speed|none)]` error: aborting due to 5 previous errors -Some errors have detailed explanations: E0658, E0722. -For more information about an error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0539, E0658. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs b/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs index 663a83a665c4..7746654555dd 100644 --- a/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs +++ b/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs @@ -17,6 +17,10 @@ fn foo(mut x: Pin<&mut Foo>) { let _y: &pin mut Foo = x; //~ ERROR pinned reference syntax is experimental } +fn foo_const(x: Pin<&Foo>) { + let _y: &pin const Foo = x; //~ ERROR pinned reference syntax is experimental +} + fn foo_sugar(_: &pin mut Foo) {} //~ ERROR pinned reference syntax is experimental fn bar(x: Pin<&mut Foo>) { @@ -31,6 +35,18 @@ fn baz(mut x: Pin<&mut Foo>) { fn baz_sugar(_: &pin const Foo) {} //~ ERROR pinned reference syntax is experimental +fn borrows() { + let mut x: Pin<&mut _> = &pin mut Foo; //~ ERROR pinned reference syntax is experimental + foo(x.as_mut()); + foo(x.as_mut()); + foo_const(x.as_ref()); + + let x: Pin<&_> = &pin const Foo; //~ ERROR pinned reference syntax is experimental + + foo_const(x); + foo_const(x); +} + #[cfg(any())] mod not_compiled { use std::pin::Pin; @@ -63,6 +79,18 @@ mod not_compiled { } fn baz_sugar(_: &pin const Foo) {} //~ ERROR pinned reference syntax is experimental + + fn borrows() { + let mut x: Pin<&mut _> = &pin mut Foo; //~ ERROR pinned reference syntax is experimental + foo(x.as_mut()); + foo(x.as_mut()); + foo_const(x.as_ref()); + + let x: Pin<&_> = &pin const Foo; //~ ERROR pinned reference syntax is experimental + + foo_const(x); + foo_const(x); + } } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr b/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr index 8ed7543d86e3..a8890254face 100644 --- a/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr +++ b/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr @@ -29,7 +29,17 @@ LL | let _y: &pin mut Foo = x; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:20:18 + --> $DIR/feature-gate-pin_ergonomics.rs:21:14 + | +LL | let _y: &pin const Foo = x; + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:24:18 | LL | fn foo_sugar(_: &pin mut Foo) {} | ^^^ @@ -39,7 +49,7 @@ LL | fn foo_sugar(_: &pin mut Foo) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:32:18 + --> $DIR/feature-gate-pin_ergonomics.rs:36:18 | LL | fn baz_sugar(_: &pin const Foo) {} | ^^^ @@ -49,7 +59,27 @@ LL | fn baz_sugar(_: &pin const Foo) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:43:23 + --> $DIR/feature-gate-pin_ergonomics.rs:39:31 + | +LL | let mut x: Pin<&mut _> = &pin mut Foo; + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:44:23 + | +LL | let x: Pin<&_> = &pin const Foo; + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:59:23 | LL | fn foo_sugar(&pin mut self) {} | ^^^ @@ -59,7 +89,7 @@ LL | fn foo_sugar(&pin mut self) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:44:29 + --> $DIR/feature-gate-pin_ergonomics.rs:60:29 | LL | fn foo_sugar_const(&pin const self) {} | ^^^ @@ -69,7 +99,7 @@ LL | fn foo_sugar_const(&pin const self) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:50:18 + --> $DIR/feature-gate-pin_ergonomics.rs:66:18 | LL | let _y: &pin mut Foo = x; | ^^^ @@ -79,7 +109,7 @@ LL | let _y: &pin mut Foo = x; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:53:22 + --> $DIR/feature-gate-pin_ergonomics.rs:69:22 | LL | fn foo_sugar(_: &pin mut Foo) {} | ^^^ @@ -89,7 +119,7 @@ LL | fn foo_sugar(_: &pin mut Foo) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pinned reference syntax is experimental - --> $DIR/feature-gate-pin_ergonomics.rs:65:22 + --> $DIR/feature-gate-pin_ergonomics.rs:81:22 | LL | fn baz_sugar(_: &pin const Foo) {} | ^^^ @@ -98,8 +128,28 @@ LL | fn baz_sugar(_: &pin const Foo) {} = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:84:35 + | +LL | let mut x: Pin<&mut _> = &pin mut Foo; + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: pinned reference syntax is experimental + --> $DIR/feature-gate-pin_ergonomics.rs:89:27 + | +LL | let x: Pin<&_> = &pin const Foo; + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0382]: use of moved value: `x` - --> $DIR/feature-gate-pin_ergonomics.rs:24:9 + --> $DIR/feature-gate-pin_ergonomics.rs:28:9 | LL | fn bar(x: Pin<&mut Foo>) { | - move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait @@ -117,7 +167,7 @@ LL | fn foo(mut x: Pin<&mut Foo>) { | in this function error[E0382]: use of moved value: `x` - --> $DIR/feature-gate-pin_ergonomics.rs:29:5 + --> $DIR/feature-gate-pin_ergonomics.rs:33:5 | LL | fn baz(mut x: Pin<&mut Foo>) { | ----- move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait @@ -136,7 +186,7 @@ help: consider reborrowing the `Pin` instead of moving it LL | x.as_mut().foo(); | +++++++++ -error: aborting due to 12 previous errors +error: aborting due to 17 previous errors Some errors have detailed explanations: E0382, E0658. For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs index b5fbcc9ccf8c..c14698637927 100644 --- a/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs +++ b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs @@ -1,4 +1,4 @@ fn main() { let _ : &(dyn Send,) = &((),); - //~^ ERROR 2:28: 2:34: mismatched types [E0308] + //~^ ERROR mismatched types [E0308] } diff --git a/tests/ui/feature-gates/gated-bad-feature.rs b/tests/ui/feature-gates/gated-bad-feature.rs index 3114f661dc5b..51f2db5556e2 100644 --- a/tests/ui/feature-gates/gated-bad-feature.rs +++ b/tests/ui/feature-gates/gated-bad-feature.rs @@ -1,4 +1,3 @@ -//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION" #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)] //~^ ERROR malformed `feature` //~| ERROR malformed `feature` diff --git a/tests/ui/feature-gates/gated-bad-feature.stderr b/tests/ui/feature-gates/gated-bad-feature.stderr index 0e75dff14f8a..e0e84d842352 100644 --- a/tests/ui/feature-gates/gated-bad-feature.stderr +++ b/tests/ui/feature-gates/gated-bad-feature.stderr @@ -1,43 +1,43 @@ error[E0556]: malformed `feature` attribute input - --> $DIR/gated-bad-feature.rs:2:25 + --> $DIR/gated-bad-feature.rs:1:25 | LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)] | ^^^^^^^^ help: expected just one word: `foo` error[E0556]: malformed `feature` attribute input - --> $DIR/gated-bad-feature.rs:2:35 + --> $DIR/gated-bad-feature.rs:1:35 | LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)] | ^^^^^^^^^^^ help: expected just one word: `foo` error[E0557]: feature has been removed - --> $DIR/gated-bad-feature.rs:9:12 + --> $DIR/gated-bad-feature.rs:8:12 | LL | #![feature(test_removed_feature)] | ^^^^^^^^^^^^^^^^^^^^ feature has been removed | - = note: removed in 1.0.0 (you are using $RUSTC_VERSION) + = note: removed in 1.0.0 error: malformed `feature` attribute input - --> $DIR/gated-bad-feature.rs:7:1 + --> $DIR/gated-bad-feature.rs:6:1 | LL | #![feature] | ^^^^^^^^^^^ help: must be of the form: `#![feature(name1, name2, ...)]` error: malformed `feature` attribute input - --> $DIR/gated-bad-feature.rs:8:1 + --> $DIR/gated-bad-feature.rs:7:1 | LL | #![feature = "foo"] | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![feature(name1, name2, ...)]` error[E0635]: unknown feature `foo_bar_baz` - --> $DIR/gated-bad-feature.rs:2:12 + --> $DIR/gated-bad-feature.rs:1:12 | LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)] | ^^^^^^^^^^^ error[E0635]: unknown feature `foo` - --> $DIR/gated-bad-feature.rs:2:48 + --> $DIR/gated-bad-feature.rs:1:48 | LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)] | ^^^ diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index 1c6868dc95d9..d2b1d71ab87c 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -379,14 +379,6 @@ warning: `#[proc_macro_derive]` only has an effect on functions LL | #![proc_macro_derive()] | ^^^^^^^^^^^^^^^^^^^^^^^ -warning: attribute should be applied to a function definition - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1 - | -LL | #![cold] - | ^^^^^^^^ cannot be applied to crates - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1 | @@ -411,6 +403,14 @@ LL | #![link_section = "1800"] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +warning: attribute should be applied to a function definition + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1 + | +LL | #![cold] + | ^^^^^^^^ cannot be applied to crates + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + warning: `#[must_use]` has no effect when applied to a module --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1 | diff --git a/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.rs b/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.rs index ec6adb471ba5..d8c5f48f9fd9 100644 --- a/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.rs +++ b/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.rs @@ -1,5 +1,3 @@ -//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION" - #![feature(external_doc)] //~ ERROR feature has been removed #![doc(include("README.md"))] //~ ERROR unknown `doc` attribute `include` diff --git a/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.stderr b/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.stderr index 43205c7360b2..bd8c56c61c3c 100644 --- a/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.stderr +++ b/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.stderr @@ -1,14 +1,14 @@ error[E0557]: feature has been removed - --> $DIR/removed-features-note-version-and-pr-issue-141619.rs:3:12 + --> $DIR/removed-features-note-version-and-pr-issue-141619.rs:1:12 | LL | #![feature(external_doc)] | ^^^^^^^^^^^^ feature has been removed | - = note: removed in 1.54.0 (you are using $RUSTC_VERSION); see for more information + = note: removed in 1.54.0; see for more information = note: use #[doc = include_str!("filename")] instead, which handles macro invocations error: unknown `doc` attribute `include` - --> $DIR/removed-features-note-version-and-pr-issue-141619.rs:4:8 + --> $DIR/removed-features-note-version-and-pr-issue-141619.rs:2:8 | LL | #![doc(include("README.md"))] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/fmt/format-args-argument-span.stderr b/tests/ui/fmt/format-args-argument-span.stderr index 4e2702383d6c..d46cfb438cf6 100644 --- a/tests/ui/fmt/format-args-argument-span.stderr +++ b/tests/ui/fmt/format-args-argument-span.stderr @@ -12,7 +12,9 @@ error[E0277]: `Option<{integer}>` doesn't implement `std::fmt::Display` --> $DIR/format-args-argument-span.rs:15:37 | LL | println!("{x:?} {x} {x:?}", x = Some(1)); - | ^^^^^^^ `Option<{integer}>` cannot be formatted with the default formatter + | --- ^^^^^^^ `Option<{integer}>` cannot be formatted with the default formatter + | | + | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `Option<{integer}>` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead @@ -22,7 +24,7 @@ error[E0277]: `DisplayOnly` doesn't implement `Debug` --> $DIR/format-args-argument-span.rs:18:19 | LL | println!("{x} {x:?} {x}"); - | ^^^^^ `DisplayOnly` cannot be formatted using `{:?}` + | ^^^^^ `DisplayOnly` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `DisplayOnly` = note: add `#[derive(Debug)]` to `DisplayOnly` or manually `impl Debug for DisplayOnly` @@ -37,7 +39,9 @@ error[E0277]: `DisplayOnly` doesn't implement `Debug` --> $DIR/format-args-argument-span.rs:20:35 | LL | println!("{x} {x:?} {x}", x = DisplayOnly); - | ^^^^^^^^^^^ `DisplayOnly` cannot be formatted using `{:?}` + | ----- ^^^^^^^^^^^ `DisplayOnly` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter | = help: the trait `Debug` is not implemented for `DisplayOnly` = note: add `#[derive(Debug)]` to `DisplayOnly` or manually `impl Debug for DisplayOnly` diff --git a/tests/ui/fmt/ifmt-unimpl.stderr b/tests/ui/fmt/ifmt-unimpl.stderr index b8d4425a4a71..5e80f892dcb5 100644 --- a/tests/ui/fmt/ifmt-unimpl.stderr +++ b/tests/ui/fmt/ifmt-unimpl.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `str: UpperHex` is not satisfied LL | format!("{:X}", "3"); | ---- ^^^ the trait `UpperHex` is not implemented for `str` | | - | required by a bound introduced by this call + | required by this formatting parameter | = help: the following other types implement trait `UpperHex`: &T @@ -17,8 +17,6 @@ LL | format!("{:X}", "3"); i32 and 9 others = note: required for `&str` to implement `UpperHex` -note: required by a bound in `core::fmt::rt::Argument::<'_>::new_upper_hex` - --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/fmt/non-source-literals.rs b/tests/ui/fmt/non-source-literals.rs new file mode 100644 index 000000000000..e3ffdb40a6b7 --- /dev/null +++ b/tests/ui/fmt/non-source-literals.rs @@ -0,0 +1,13 @@ +/// Do not point at the format string if it wasn't written in the source. +//@ forbid-output: required by this formatting parameter + +#[derive(Debug)] +pub struct NonDisplay; +pub struct NonDebug; + +fn main() { + let _ = format!(concat!("{", "}"), NonDisplay); //~ ERROR + let _ = format!(concat!("{", "0", "}"), NonDisplay); //~ ERROR + let _ = format!(concat!("{:", "?}"), NonDebug); //~ ERROR + let _ = format!(concat!("{", "0", ":?}"), NonDebug); //~ ERROR +} diff --git a/tests/ui/fmt/non-source-literals.stderr b/tests/ui/fmt/non-source-literals.stderr new file mode 100644 index 000000000000..5f8a6200dab7 --- /dev/null +++ b/tests/ui/fmt/non-source-literals.stderr @@ -0,0 +1,53 @@ +error[E0277]: `NonDisplay` doesn't implement `std::fmt::Display` + --> $DIR/non-source-literals.rs:9:40 + | +LL | let _ = format!(concat!("{", "}"), NonDisplay); + | ^^^^^^^^^^ `NonDisplay` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `NonDisplay` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `NonDisplay` doesn't implement `std::fmt::Display` + --> $DIR/non-source-literals.rs:10:45 + | +LL | let _ = format!(concat!("{", "0", "}"), NonDisplay); + | ^^^^^^^^^^ `NonDisplay` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `NonDisplay` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `NonDebug` doesn't implement `Debug` + --> $DIR/non-source-literals.rs:11:42 + | +LL | let _ = format!(concat!("{:", "?}"), NonDebug); + | ^^^^^^^^ `NonDebug` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = help: the trait `Debug` is not implemented for `NonDebug` + = note: add `#[derive(Debug)]` to `NonDebug` or manually `impl Debug for NonDebug` + = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `NonDebug` with `#[derive(Debug)]` + | +LL + #[derive(Debug)] +LL | pub struct NonDebug; + | + +error[E0277]: `NonDebug` doesn't implement `Debug` + --> $DIR/non-source-literals.rs:12:47 + | +LL | let _ = format!(concat!("{", "0", ":?}"), NonDebug); + | ^^^^^^^^ `NonDebug` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = help: the trait `Debug` is not implemented for `NonDebug` + = note: add `#[derive(Debug)]` to `NonDebug` or manually `impl Debug for NonDebug` + = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `NonDebug` with `#[derive(Debug)]` + | +LL + #[derive(Debug)] +LL | pub struct NonDebug; + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/generic-associated-types-where.stderr b/tests/ui/generic-associated-types/generic-associated-types-where.stderr index 7dce34650d78..637f86f7bec2 100644 --- a/tests/ui/generic-associated-types/generic-associated-types-where.stderr +++ b/tests/ui/generic-associated-types/generic-associated-types-where.stderr @@ -2,9 +2,8 @@ error[E0277]: `T` doesn't implement `std::fmt::Display` --> $DIR/generic-associated-types-where.rs:18:22 | LL | type Assoc2 = Vec; - | ^^^^^^ `T` cannot be formatted with the default formatter + | ^^^^^^ the trait `std::fmt::Display` is not implemented for `T` | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead help: consider restricting type parameter `T` with trait `Display` | LL | type Assoc2 = Vec; diff --git a/tests/ui/generics/default-type-params-well-formedness.rs b/tests/ui/generics/default-type-params-well-formedness.rs new file mode 100644 index 000000000000..22b8f5011f7e --- /dev/null +++ b/tests/ui/generics/default-type-params-well-formedness.rs @@ -0,0 +1,50 @@ +//! Test for well-formedness checking of default type parameters. +//! +//! Regression Test for: https://github.com/rust-lang/rust/issues/49344 + +//@ run-pass + +#![allow(dead_code)] + +trait Trait {} +struct Foo(U, V) +where + U: Trait; + +trait Marker {} +struct TwoParams(T, U); +impl Marker for TwoParams {} + +// Clauses with more than 1 param are not checked. +struct IndividuallyBogus(TwoParams) +where + TwoParams: Marker; + +struct BogusTogether(T, U) +where + TwoParams: Marker; + +// Clauses with non-defaulted params are not checked. +struct NonDefaultedInClause(TwoParams) +where + TwoParams: Marker; + +struct DefaultedLhs(U, V) +where + V: Trait; + +// Dependent defaults are not checked. +struct Dependent(T, U) +where + U: Copy; + +trait SelfBound {} + +// Not even for well-formedness. +struct WellFormedProjection::Item>(A, T); + +// Issue #49344, predicates with lifetimes should not be checked. +trait Scope<'a> {} +struct Request<'a, S: Scope<'a> = i32>(S, &'a ()); + +fn main() {} diff --git a/tests/ui/hygiene/no_implicit_prelude.stderr b/tests/ui/hygiene/no_implicit_prelude.stderr index 5de6e3db327b..42049da23eb5 100644 --- a/tests/ui/hygiene/no_implicit_prelude.stderr +++ b/tests/ui/hygiene/no_implicit_prelude.stderr @@ -23,8 +23,6 @@ LL | ().clone() | ^^^^^ | = help: items from traits can only be used if the trait is in scope -help: there is a method `clone_from` with a similar name, but with different arguments - --> $SRC_DIR/core/src/clone.rs:LL:COL = note: this error originates in the macro `::bar::m` (in Nightly builds, run with -Z macro-backtrace for more info) help: trait `Clone` which provides `clone` is implemented but not in scope; perhaps you want to import it | diff --git a/tests/ui/impl-header-lifetime-elision/assoc-type.rs b/tests/ui/impl-header-lifetime-elision/assoc-type.rs index db3c416540fc..14b2ea647f19 100644 --- a/tests/ui/impl-header-lifetime-elision/assoc-type.rs +++ b/tests/ui/impl-header-lifetime-elision/assoc-type.rs @@ -9,7 +9,7 @@ trait MyTrait { impl MyTrait for &i32 { type Output = &i32; - //~^ ERROR 11:19: 11:20: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type + //~^ ERROR in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type } impl MyTrait for &u32 { diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed index 886fc1d00580..d8eceeff6788 100644 --- a/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed +++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed @@ -1,5 +1,6 @@ //@ run-rustfix +#![allow(dead_code)] struct S(T); struct S2; diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.rs b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs index f3271993867c..c2e511c0d055 100644 --- a/tests/ui/impl-trait/extra-impl-in-trait-impl.rs +++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs @@ -1,5 +1,6 @@ //@ run-rustfix +#![allow(dead_code)] struct S(T); struct S2; diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr index 5aafc8b64d4f..22e68463a8cf 100644 --- a/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr +++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr @@ -1,23 +1,23 @@ error: unexpected `impl` keyword - --> $DIR/extra-impl-in-trait-impl.rs:6:18 + --> $DIR/extra-impl-in-trait-impl.rs:7:18 | LL | impl impl Default for S { | ^^^^^ help: remove the extra `impl` | note: this is parsed as an `impl Trait` type, but a trait is expected at this position - --> $DIR/extra-impl-in-trait-impl.rs:6:18 + --> $DIR/extra-impl-in-trait-impl.rs:7:18 | LL | impl impl Default for S { | ^^^^^^^^^^^^ error: unexpected `impl` keyword - --> $DIR/extra-impl-in-trait-impl.rs:12:6 + --> $DIR/extra-impl-in-trait-impl.rs:13:6 | LL | impl impl Default for S2 { | ^^^^^ help: remove the extra `impl` | note: this is parsed as an `impl Trait` type, but a trait is expected at this position - --> $DIR/extra-impl-in-trait-impl.rs:12:6 + --> $DIR/extra-impl-in-trait-impl.rs:13:6 | LL | impl impl Default for S2 { | ^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/in-bindings/lifetime-equality.rs b/tests/ui/impl-trait/in-bindings/lifetime-equality.rs new file mode 100644 index 000000000000..6cf48dccc7d9 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/lifetime-equality.rs @@ -0,0 +1,19 @@ +//@ check-pass + +#![feature(impl_trait_in_bindings)] + +// A test for #61773 which would have been difficult to support if we +// were to represent `impl_trait_in_bindings` using opaque types. + +trait Trait<'a, 'b> { } +impl Trait<'_, '_> for T { } + + +fn bar<'a, 'b>(data0: &'a u32, data1: &'b u32) { + let x: impl Trait<'_, '_> = (data0, data1); + force_equal(x); +} + +fn force_equal<'a>(t: impl Trait<'a, 'a>) { } + +fn main() { } diff --git a/tests/ui/impl-trait/in-bindings/region-lifetimes.rs b/tests/ui/impl-trait/in-bindings/region-lifetimes.rs new file mode 100644 index 000000000000..189ab85a2769 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/region-lifetimes.rs @@ -0,0 +1,17 @@ +//@ check-pass + +#![feature(impl_trait_in_bindings)] + +// A test for #61773 which would have been difficult to support if we +// were to represent `impl_trait_in_bindings` using opaque types. + +trait Foo<'a> { } +impl Foo<'_> for &u32 { } + +fn bar<'a>(data: &'a u32) { + let x: impl Foo<'_> = data; +} + +fn main() { + let _: impl Foo<'_> = &44; +} diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr index 119195f17ffc..df89ed9f3b56 100644 --- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr @@ -2,10 +2,8 @@ error[E0277]: `()` doesn't implement `std::fmt::Display` --> $DIR/doesnt-satisfy.rs:6:17 | LL | fn bar() -> () {} - | ^^ `()` cannot be formatted with the default formatter + | ^^ the trait `std::fmt::Display` is not implemented for `()` | - = help: the trait `std::fmt::Display` is not implemented for `()` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `Foo::bar::{anon_assoc#0}` --> $DIR/doesnt-satisfy.rs:2:22 | diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.stderr index 634557094ced..40a029cdc920 100644 --- a/tests/ui/impl-trait/in-trait/wf-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/wf-bounds.stderr @@ -39,9 +39,8 @@ error[E0277]: `T` doesn't implement `std::fmt::Display` --> $DIR/wf-bounds.rs:21:26 | LL | fn nya4() -> impl Wf>; - | ^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | ^^^^^^^^^^^^^^^^^^^ the trait `std::fmt::Display` is not implemented for `T` | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `NeedsDisplay` --> $DIR/wf-bounds.rs:9:24 | diff --git a/tests/ui/impl-trait/precise-capturing/foreign-2021.stderr b/tests/ui/impl-trait/precise-capturing/foreign-2021.stderr index cd9ed0fb8851..1dcd800cfc51 100644 --- a/tests/ui/impl-trait/precise-capturing/foreign-2021.stderr +++ b/tests/ui/impl-trait/precise-capturing/foreign-2021.stderr @@ -8,7 +8,7 @@ LL | x.push(0); | ^^^^^^^^^ mutable borrow occurs here ... LL | println!("{h}"); - | --- immutable borrow later used here + | - immutable borrow later used here | note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules --> $DIR/foreign-2021.rs:7:13 diff --git a/tests/ui/impl-trait/precise-capturing/migration-note.stderr b/tests/ui/impl-trait/precise-capturing/migration-note.stderr index 676b6c12f52a..aa0f64000915 100644 --- a/tests/ui/impl-trait/precise-capturing/migration-note.stderr +++ b/tests/ui/impl-trait/precise-capturing/migration-note.stderr @@ -23,7 +23,7 @@ LL | x.push(1); | ^^^^^^^^^ mutable borrow occurs here ... LL | println!("{a}"); - | --- immutable borrow later used here + | - immutable borrow later used here | note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules --> $DIR/migration-note.rs:16:13 @@ -99,7 +99,7 @@ LL | x.push(1); | ^ second mutable borrow occurs here ... LL | println!("{a}"); - | --- first borrow later used here + | - first borrow later used here | note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules --> $DIR/migration-note.rs:63:13 @@ -175,7 +175,7 @@ LL | s.f = 1; | ^^^^^^^ `s.f` is assigned to here but it was already borrowed ... LL | println!("{a}"); - | --- borrow later used here + | - borrow later used here | note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules --> $DIR/migration-note.rs:112:13 @@ -197,7 +197,7 @@ LL | s.f = 1; | ^^^^^^^ `s.f` is assigned to here but it was already borrowed ... LL | println!("{a}"); - | --- borrow later used here + | - borrow later used here | note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules --> $DIR/migration-note.rs:128:13 @@ -219,7 +219,7 @@ LL | s.f; | ^^^ use of borrowed `s.f` ... LL | println!("{a}"); - | --- borrow later used here + | - borrow later used here | note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules --> $DIR/migration-note.rs:140:13 diff --git a/tests/ui/imports/issue-28134.rs b/tests/ui/imports/issue-28134.rs index 70d3a327c1af..aef2fe8facdc 100644 --- a/tests/ui/imports/issue-28134.rs +++ b/tests/ui/imports/issue-28134.rs @@ -2,4 +2,4 @@ #![allow(soft_unstable)] #![test] -//~^ ERROR 4:1: 4:9: `test` attribute cannot be used at crate level +//~^ ERROR `test` attribute cannot be used at crate level diff --git a/tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr b/tests/ui/imports/multiple-extern-by-macro-for-underscore.ed2015.stderr similarity index 75% rename from tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr rename to tests/ui/imports/multiple-extern-by-macro-for-underscore.ed2015.stderr index 1da5aa870704..985cd654c394 100644 --- a/tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr +++ b/tests/ui/imports/multiple-extern-by-macro-for-underscore.ed2015.stderr @@ -1,5 +1,5 @@ error: expected identifier, found reserved identifier `_` - --> $DIR/multiple-extern-by-macro-for-underscore.rs:16:11 + --> $DIR/multiple-extern-by-macro-for-underscore.rs:18:11 | LL | use ::_; | ^ expected identifier, found reserved identifier diff --git a/tests/ui/imports/multiple-extern-by-macro-for-underscore.ed2021.stderr b/tests/ui/imports/multiple-extern-by-macro-for-underscore.ed2021.stderr new file mode 100644 index 000000000000..985cd654c394 --- /dev/null +++ b/tests/ui/imports/multiple-extern-by-macro-for-underscore.ed2021.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/multiple-extern-by-macro-for-underscore.rs:18:11 + | +LL | use ::_; + | ^ expected identifier, found reserved identifier + +error: aborting due to 1 previous error + diff --git a/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs b/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs index ddf735d89475..ab877e062463 100644 --- a/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs +++ b/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs @@ -1,4 +1,6 @@ -//@ edition: 2021 +//@ revisions: ed2015 ed2021 +//@[ed2015] edition: 2015 +//@[ed2021] edition: 2021 // issue#128813 diff --git a/tests/ui/inference/hint-closure-signature-119266.rs b/tests/ui/inference/hint-closure-signature-119266.rs index 35be600fd6ab..6e136c57ccad 100644 --- a/tests/ui/inference/hint-closure-signature-119266.rs +++ b/tests/ui/inference/hint-closure-signature-119266.rs @@ -3,7 +3,7 @@ fn main() { //~^ NOTE: the found closure let x: fn(i32) = x; - //~^ ERROR: 5:22: 5:23: mismatched types [E0308] + //~^ ERROR: mismatched types [E0308] //~| NOTE: incorrect number of function parameters //~| NOTE: expected due to this //~| NOTE: expected fn pointer `fn(i32)` diff --git a/tests/ui/integral-indexing.rs b/tests/ui/integral-indexing.rs index f076dfcb0a42..e20553af8a26 100644 --- a/tests/ui/integral-indexing.rs +++ b/tests/ui/integral-indexing.rs @@ -3,14 +3,14 @@ pub fn main() { let s: String = "abcdef".to_string(); v[3_usize]; v[3]; - v[3u8]; //~ERROR : the type `[isize]` cannot be indexed by `u8` - v[3i8]; //~ERROR : the type `[isize]` cannot be indexed by `i8` - v[3u32]; //~ERROR : the type `[isize]` cannot be indexed by `u32` - v[3i32]; //~ERROR : the type `[isize]` cannot be indexed by `i32` + v[3u8]; //~ ERROR the type `[isize]` cannot be indexed by `u8` + v[3i8]; //~ ERROR the type `[isize]` cannot be indexed by `i8` + v[3u32]; //~ ERROR the type `[isize]` cannot be indexed by `u32` + v[3i32]; //~ ERROR the type `[isize]` cannot be indexed by `i32` s.as_bytes()[3_usize]; s.as_bytes()[3]; - s.as_bytes()[3u8]; //~ERROR : the type `[u8]` cannot be indexed by `u8` - s.as_bytes()[3i8]; //~ERROR : the type `[u8]` cannot be indexed by `i8` - s.as_bytes()[3u32]; //~ERROR : the type `[u8]` cannot be indexed by `u32` - s.as_bytes()[3i32]; //~ERROR : the type `[u8]` cannot be indexed by `i32` + s.as_bytes()[3u8]; //~ ERROR the type `[u8]` cannot be indexed by `u8` + s.as_bytes()[3i8]; //~ ERROR the type `[u8]` cannot be indexed by `i8` + s.as_bytes()[3u32]; //~ ERROR the type `[u8]` cannot be indexed by `u32` + s.as_bytes()[3i32]; //~ ERROR the type `[u8]` cannot be indexed by `i32` } diff --git a/tests/ui/issues/issue-32950.rs b/tests/ui/issues/issue-32950.rs deleted file mode 100644 index b51ac2967768..000000000000 --- a/tests/ui/issues/issue-32950.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(concat_idents)] -#![expect(deprecated)] // concat_idents is deprecated - -#[derive(Debug)] -struct Baz( - concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros - //~^ ERROR cannot find type `FooBar` in this scope -); - -fn main() {} diff --git a/tests/ui/issues/issue-32950.stderr b/tests/ui/issues/issue-32950.stderr deleted file mode 100644 index 38a82542f896..000000000000 --- a/tests/ui/issues/issue-32950.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: `derive` cannot be used on items with type macros - --> $DIR/issue-32950.rs:6:5 - | -LL | concat_idents!(Foo, Bar) - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0412]: cannot find type `FooBar` in this scope - --> $DIR/issue-32950.rs:6:5 - | -LL | concat_idents!(Foo, Bar) - | ^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-43988.stderr b/tests/ui/issues/issue-43988.stderr index bd4eb8bbed37..fe61e136a516 100644 --- a/tests/ui/issues/issue-43988.stderr +++ b/tests/ui/issues/issue-43988.stderr @@ -38,7 +38,7 @@ LL | #[repr] | ^^^^^^^ | | | expected this to be a list - | help: must be of the form: `#[repr(C)]` + | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | | transparent)]` error[E0539]: malformed `inline` attribute input --> $DIR/issue-43988.rs:30:5 @@ -64,7 +64,7 @@ LL | let _z = #[repr] 1; | ^^^^^^^ | | | expected this to be a list - | help: must be of the form: `#[repr(C)]` + | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | | transparent)]` error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43988.rs:5:5 diff --git a/tests/ui/issues/issue-50403.rs b/tests/ui/issues/issue-50403.rs deleted file mode 100644 index f14958afc34d..000000000000 --- a/tests/ui/issues/issue-50403.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(concat_idents)] -#![expect(deprecated)] // concat_idents is deprecated - -fn main() { - let x = concat_idents!(); //~ ERROR `concat_idents!()` takes 1 or more arguments -} diff --git a/tests/ui/issues/issue-50403.stderr b/tests/ui/issues/issue-50403.stderr deleted file mode 100644 index e7dd05bb0183..000000000000 --- a/tests/ui/issues/issue-50403.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `concat_idents!()` takes 1 or more arguments - --> $DIR/issue-50403.rs:5:13 - | -LL | let x = concat_idents!(); - | ^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/issues/issue-59488.stderr b/tests/ui/issues/issue-59488.stderr index ac8862716c07..b6611ad63a81 100644 --- a/tests/ui/issues/issue-59488.stderr +++ b/tests/ui/issues/issue-59488.stderr @@ -87,18 +87,16 @@ error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` --> $DIR/issue-59488.rs:30:5 | LL | assert_eq!(Foo::Bar, i); - | ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}` | - = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` --> $DIR/issue-59488.rs:30:5 | LL | assert_eq!(Foo::Bar, i); - | ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}` | - = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 10 previous errors diff --git a/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr b/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr index b30bcfb776c8..736002c9335a 100644 --- a/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr +++ b/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr @@ -26,9 +26,8 @@ LL | fn a() -> i32 { | - consider calling this function ... LL | assert_eq!(a, 0); - | ^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for fn item `fn() -> i32 {a}` | - = help: the trait `Debug` is not implemented for fn item `fn() -> i32 {a}` = help: use parentheses to call this function: `a()` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/issues/issue-92741.rs b/tests/ui/issues/issue-92741.rs index f2e5fdafd9cb..1c5d5810a57e 100644 --- a/tests/ui/issues/issue-92741.rs +++ b/tests/ui/issues/issue-92741.rs @@ -1,17 +1,17 @@ //@ run-rustfix fn main() {} fn _foo() -> bool { - & //~ ERROR 4:5: 6:36: mismatched types [E0308] + & //~ ERROR mismatched types [E0308] mut if true { true } else { false } } fn _bar() -> bool { - & //~ ERROR 10:5: 11:40: mismatched types [E0308] + & //~ ERROR mismatched types [E0308] mut if true { true } else { false } } fn _baz() -> bool { - & mut //~ ERROR 15:5: 16:36: mismatched types [E0308] + & mut //~ ERROR mismatched types [E0308] if true { true } else { false } } diff --git a/tests/ui/lifetimes/no_lending_iterators.rs b/tests/ui/lifetimes/no_lending_iterators.rs index b3e8ad08ba18..88b8cda0898b 100644 --- a/tests/ui/lifetimes/no_lending_iterators.rs +++ b/tests/ui/lifetimes/no_lending_iterators.rs @@ -2,7 +2,7 @@ struct Data(String); impl Iterator for Data { type Item = &str; - //~^ ERROR 4:17: 4:18: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type + //~^ ERROR associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type fn next(&mut self) -> Option { Some(&self.0) @@ -16,7 +16,7 @@ trait Bar { impl Bar for usize { type Item = &usize; - //~^ ERROR 18:17: 18:18: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type + //~^ ERROR in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type fn poke(&mut self, item: Self::Item) { self += *item; @@ -25,7 +25,7 @@ impl Bar for usize { impl Bar for isize { type Item<'a> = &'a isize; - //~^ ERROR 27:14: 27:18: lifetime parameters or bounds on associated type `Item` do not match the trait declaration [E0195] + //~^ ERROR lifetime parameters or bounds on associated type `Item` do not match the trait declaration [E0195] fn poke(&mut self, item: Self::Item) { self += *item; diff --git a/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.stderr b/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.stderr index 66f9140f63cf..b0d64b531cb4 100644 --- a/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.stderr +++ b/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.stderr @@ -6,7 +6,7 @@ LL | let g = some(&temp()); | | | creates a temporary value which is freed while still in use LL | println!("{a:?} {b:?} {c:?} {d:?} {e:?} {f:?} {g:?}"); - | ----- borrow later used here + | - borrow later used here | help: consider using a `let` binding to create a longer lived value | diff --git a/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.rs b/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.rs index 9babc20d1a15..9ccc9ce4fdb8 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.rs @@ -11,7 +11,7 @@ extern crate minicore; #[link(name = "foo", kind = "raw-dylib")] extern "stdcall" { -//~^ WARN: calling convention not supported on this target +//~^ WARN: unsupported_calling_conventions //~| WARN: previously accepted fn f(x: i32); //~^ ERROR ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture diff --git a/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.stderr b/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.stderr index 95ea90804867..91e42f2909e0 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.stderr @@ -1,4 +1,4 @@ -warning: use of calling convention not supported on this target +warning: "stdcall" is not a supported ABI for the current target --> $DIR/unsupported-abi.rs:13:1 | LL | / extern "stdcall" { diff --git a/tests/ui/lint/dead-code/issue-41883.stderr b/tests/ui/lint/dead-code/issue-41883.stderr index cf079e4dda33..47ccef9a5306 100644 --- a/tests/ui/lint/dead-code/issue-41883.stderr +++ b/tests/ui/lint/dead-code/issue-41883.stderr @@ -29,8 +29,6 @@ error: struct `UnusedStruct` is never constructed | LL | struct UnusedStruct; | ^^^^^^^^^^^^ - | - = note: `UnusedStruct` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis error: aborting due to 4 previous errors diff --git a/tests/ui/lint/dead-code/issue-59003.rs b/tests/ui/lint/dead-code/issue-59003.rs index e3dcaca57788..319cf2db1495 100644 --- a/tests/ui/lint/dead-code/issue-59003.rs +++ b/tests/ui/lint/dead-code/issue-59003.rs @@ -4,8 +4,8 @@ #![deny(dead_code)] +#[allow(dead_code)] struct Foo { - #[allow(dead_code)] inner: u32, } diff --git a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs new file mode 100644 index 000000000000..25777438456b --- /dev/null +++ b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs @@ -0,0 +1,37 @@ +#![deny(dead_code)] + +struct Foo(u8); //~ ERROR struct `Foo` is never constructed + +enum Bar { //~ ERROR enum `Bar` is never used + Var1(u8), + Var2(u8), +} + +pub trait Tr1 { + fn f1() -> Self; +} + +impl Tr1 for Foo { + fn f1() -> Foo { + let f = Foo(0); + let Foo(tag) = f; + Foo(tag) + } +} + +impl Tr1 for Bar { + fn f1() -> Bar { + let b = Bar::Var1(0); + let b = if let Bar::Var1(_) = b { + Bar::Var1(0) + } else { + Bar::Var2(0) + }; + match b { + Bar::Var1(_) => Bar::Var2(0), + Bar::Var2(_) => Bar::Var1(0), + } + } +} + +fn main() {} diff --git a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr new file mode 100644 index 000000000000..7c1a4b459775 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr @@ -0,0 +1,20 @@ +error: struct `Foo` is never constructed + --> $DIR/lint-unused-adt-appeared-in-pattern.rs:3:8 + | +LL | struct Foo(u8); + | ^^^ + | +note: the lint level is defined here + --> $DIR/lint-unused-adt-appeared-in-pattern.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: enum `Bar` is never used + --> $DIR/lint-unused-adt-appeared-in-pattern.rs:5:6 + | +LL | enum Bar { + | ^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr index b992005318f2..25a7d96cb897 100644 --- a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr +++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr @@ -56,8 +56,6 @@ warning: struct `Foo` is never constructed | LL | struct Foo(usize, #[allow(unused)] usize); | ^^^ - | - = note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/tests/ui/lint/dead-code/not-lint-adt-appeared-in-pattern-issue-120770.rs b/tests/ui/lint/dead-code/not-lint-adt-appeared-in-pattern-issue-120770.rs new file mode 100644 index 000000000000..43a2e4319043 --- /dev/null +++ b/tests/ui/lint/dead-code/not-lint-adt-appeared-in-pattern-issue-120770.rs @@ -0,0 +1,32 @@ +//@ check-pass + +#![deny(dead_code)] + +#[repr(u8)] +#[derive(Copy, Clone, Debug)] +pub enum RecordField { + Target = 1, + Level, + Module, + File, + Line, + NumArgs, +} + +unsafe trait Pod {} + +#[repr(transparent)] +struct RecordFieldWrapper(RecordField); + +unsafe impl Pod for RecordFieldWrapper {} + +fn try_read(buf: &[u8]) -> T { + unsafe { std::ptr::read_unaligned(buf.as_ptr() as *const T) } +} + +pub fn foo(buf: &[u8]) -> RecordField { + let RecordFieldWrapper(tag) = try_read(buf); + tag +} + +fn main() {} diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs index 5b755d62a059..415eb4138def 100644 --- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs +++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs @@ -2,7 +2,7 @@ struct T1; //~ ERROR struct `T1` is never constructed pub struct T2(i32); //~ ERROR field `0` is never read -struct T3; +struct T3; //~ ERROR struct `T3` is never constructed trait Trait1 { //~ ERROR trait `Trait1` is never used const UNUSED: i32; diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr index 2441a3f868dc..778dadee153f 100644 --- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr +++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr @@ -20,11 +20,17 @@ LL | pub struct T2(i32); | = help: consider removing this field +error: struct `T3` is never constructed + --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:5:8 + | +LL | struct T3; + | ^^ + error: trait `Trait1` is never used --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:7:7 | LL | trait Trait1 { | ^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.rs b/tests/ui/lint/dead-code/unused-struct-derive-default.rs index 330ad32dd570..f20b7cb66ee5 100644 --- a/tests/ui/lint/dead-code/unused-struct-derive-default.rs +++ b/tests/ui/lint/dead-code/unused-struct-derive-default.rs @@ -22,4 +22,5 @@ pub struct T2 { fn main() { let _x: Used = Default::default(); + let _e: E = Default::default(); } diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.stderr b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr index bbb0bd7be706..7422f9a39f31 100644 --- a/tests/ui/lint/dead-code/unused-struct-derive-default.stderr +++ b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr @@ -4,7 +4,6 @@ error: struct `T` is never constructed LL | struct T; | ^ | - = note: `T` has a derived impl for the trait `Default`, but this is intentionally ignored during dead code analysis note: the lint level is defined here --> $DIR/unused-struct-derive-default.rs:1:9 | diff --git a/tests/ui/lint/lint-non-uppercase-usages.fixed b/tests/ui/lint/lint-non-uppercase-usages.fixed new file mode 100644 index 000000000000..231991dcae08 --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-usages.fixed @@ -0,0 +1,44 @@ +// Checks that the `non_upper_case_globals` emits suggestions for usages as well +// + +//@ check-pass +//@ run-rustfix + +#![allow(dead_code)] + +use std::cell::Cell; + +const MY_STATIC: u32 = 0; +//~^ WARN constant `my_static` should have an upper case name +//~| SUGGESTION MY_STATIC + +const LOL: u32 = MY_STATIC + 0; +//~^ SUGGESTION MY_STATIC + +mod my_mod { + const INSIDE_MOD: u32 = super::MY_STATIC + 0; + //~^ SUGGESTION MY_STATIC +} + +thread_local! { + static FOO_FOO: Cell = unreachable!(); + //~^ WARN constant `fooFOO` should have an upper case name + //~| SUGGESTION FOO_FOO +} + +fn foo() { + //~^ WARN const parameter `foo` should have an upper case name + //~| SUGGESTION FOO + let _a = FOO + 1; + //~^ SUGGESTION FOO +} + +fn main() { + let _a = crate::MY_STATIC; + //~^ SUGGESTION MY_STATIC + + FOO_FOO.set(9); + //~^ SUGGESTION FOO_FOO + println!("{}", FOO_FOO.get()); + //~^ SUGGESTION FOO_FOO +} diff --git a/tests/ui/lint/lint-non-uppercase-usages.rs b/tests/ui/lint/lint-non-uppercase-usages.rs new file mode 100644 index 000000000000..9cdf5e47003d --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-usages.rs @@ -0,0 +1,44 @@ +// Checks that the `non_upper_case_globals` emits suggestions for usages as well +// + +//@ check-pass +//@ run-rustfix + +#![allow(dead_code)] + +use std::cell::Cell; + +const my_static: u32 = 0; +//~^ WARN constant `my_static` should have an upper case name +//~| SUGGESTION MY_STATIC + +const LOL: u32 = my_static + 0; +//~^ SUGGESTION MY_STATIC + +mod my_mod { + const INSIDE_MOD: u32 = super::my_static + 0; + //~^ SUGGESTION MY_STATIC +} + +thread_local! { + static fooFOO: Cell = unreachable!(); + //~^ WARN constant `fooFOO` should have an upper case name + //~| SUGGESTION FOO_FOO +} + +fn foo() { + //~^ WARN const parameter `foo` should have an upper case name + //~| SUGGESTION FOO + let _a = foo + 1; + //~^ SUGGESTION FOO +} + +fn main() { + let _a = crate::my_static; + //~^ SUGGESTION MY_STATIC + + fooFOO.set(9); + //~^ SUGGESTION FOO_FOO + println!("{}", fooFOO.get()); + //~^ SUGGESTION FOO_FOO +} diff --git a/tests/ui/lint/lint-non-uppercase-usages.stderr b/tests/ui/lint/lint-non-uppercase-usages.stderr new file mode 100644 index 000000000000..7c7e573a88ed --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-usages.stderr @@ -0,0 +1,39 @@ +warning: constant `my_static` should have an upper case name + --> $DIR/lint-non-uppercase-usages.rs:11:7 + | +LL | const my_static: u32 = 0; + | ^^^^^^^^^ + | + = note: `#[warn(non_upper_case_globals)]` on by default +help: convert the identifier to upper case + | +LL - const my_static: u32 = 0; +LL + const MY_STATIC: u32 = 0; + | + +warning: constant `fooFOO` should have an upper case name + --> $DIR/lint-non-uppercase-usages.rs:24:12 + | +LL | static fooFOO: Cell = unreachable!(); + | ^^^^^^ + | +help: convert the identifier to upper case + | +LL - static fooFOO: Cell = unreachable!(); +LL + static FOO_FOO: Cell = unreachable!(); + | + +warning: const parameter `foo` should have an upper case name + --> $DIR/lint-non-uppercase-usages.rs:29:14 + | +LL | fn foo() { + | ^^^ + | +help: convert the identifier to upper case (notice the capitalization difference) + | +LL - fn foo() { +LL + fn foo() { + | + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr index e1c45e832af3..df6cada6b06f 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.stderr +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -65,19 +65,6 @@ LL | #[should_panic] | ^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error: unused attribute - --> $DIR/unused-attr-duplicate.rs:60:1 - | -LL | #[must_use = "some message"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:59:1 - | -LL | #[must_use] - | ^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - error: unused attribute --> $DIR/unused-attr-duplicate.rs:66:1 | @@ -102,30 +89,6 @@ note: attribute also specified here LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: unused attribute - --> $DIR/unused-attr-duplicate.rs:77:1 - | -LL | #[cold] - | ^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:76:1 - | -LL | #[cold] - | ^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr-duplicate.rs:79:1 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:78:1 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ - error: unused attribute --> $DIR/unused-attr-duplicate.rs:92:1 | @@ -139,18 +102,6 @@ LL | #[export_name = "exported_symbol_name2"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error: unused attribute - --> $DIR/unused-attr-duplicate.rs:98:1 - | -LL | #[no_mangle] - | ^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:97:1 - | -LL | #[no_mangle] - | ^^^^^^^^^^^^ - error: unused attribute --> $DIR/unused-attr-duplicate.rs:102:1 | @@ -276,6 +227,19 @@ note: attribute also specified here LL | #[macro_export] | ^^^^^^^^^^^^^^^ +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:60:1 + | +LL | #[must_use = "some message"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:59:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + error: unused attribute --> $DIR/unused-attr-duplicate.rs:74:1 | @@ -289,5 +253,41 @@ LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:77:1 + | +LL | #[cold] + | ^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:76:1 + | +LL | #[cold] + | ^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:79:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:78:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:98:1 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:97:1 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ + error: aborting due to 23 previous errors diff --git a/tests/ui/loop-match/break-to-block.rs b/tests/ui/loop-match/break-to-block.rs new file mode 100644 index 000000000000..e7451a944c39 --- /dev/null +++ b/tests/ui/loop-match/break-to-block.rs @@ -0,0 +1,23 @@ +// Test that a `break` without `#[const_continue]` still works as expected. + +//@ run-pass + +#![allow(incomplete_features)] +#![feature(loop_match)] + +fn main() { + assert_eq!(helper(), 1); +} + +fn helper() -> u8 { + let mut state = 0u8; + #[loop_match] + 'a: loop { + state = 'blk: { + match state { + 0 => break 'blk 1, + _ => break 'a state, + } + } + } +} diff --git a/tests/ui/loop-match/const-continue-to-block.rs b/tests/ui/loop-match/const-continue-to-block.rs new file mode 100644 index 000000000000..fd7ebeefeb64 --- /dev/null +++ b/tests/ui/loop-match/const-continue-to-block.rs @@ -0,0 +1,26 @@ +// Test that a `#[const_continue]` that breaks to a normal labeled block (that +// is not part of a `#[loop_match]`) produces an error. + +#![allow(incomplete_features)] +#![feature(loop_match)] +#![crate_type = "lib"] + +fn const_continue_to_block() -> u8 { + let state = 0; + #[loop_match] + loop { + state = 'blk: { + match state { + 0 => { + #[const_continue] + break 'blk 1; + } + _ => 'b: { + #[const_continue] + break 'b 2; + //~^ ERROR `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]` + } + } + } + } +} diff --git a/tests/ui/loop-match/const-continue-to-block.stderr b/tests/ui/loop-match/const-continue-to-block.stderr new file mode 100644 index 000000000000..3a5339a03949 --- /dev/null +++ b/tests/ui/loop-match/const-continue-to-block.stderr @@ -0,0 +1,8 @@ +error: `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]` + --> $DIR/const-continue-to-block.rs:20:27 + | +LL | break 'b 2; + | ^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/loop-match/const-continue-to-loop.rs b/tests/ui/loop-match/const-continue-to-loop.rs new file mode 100644 index 000000000000..c363e617cfb7 --- /dev/null +++ b/tests/ui/loop-match/const-continue-to-loop.rs @@ -0,0 +1,27 @@ +// Test that a `#[const_continue]` that breaks to the label of the loop itself +// rather than to the label of the block within the `#[loop_match]` produces an +// error. + +#![allow(incomplete_features)] +#![feature(loop_match)] +#![crate_type = "lib"] + +fn const_continue_to_loop() -> u8 { + let mut state = 0; + #[loop_match] + 'a: loop { + state = 'blk: { + match state { + 0 => { + #[const_continue] + break 'blk 1; + } + _ => { + #[const_continue] + break 'a 2; + //~^ ERROR `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]` + } + } + } + } +} diff --git a/tests/ui/loop-match/const-continue-to-loop.stderr b/tests/ui/loop-match/const-continue-to-loop.stderr new file mode 100644 index 000000000000..a217b3ac72c7 --- /dev/null +++ b/tests/ui/loop-match/const-continue-to-loop.stderr @@ -0,0 +1,8 @@ +error: `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]` + --> $DIR/const-continue-to-loop.rs:21:27 + | +LL | break 'a 2; + | ^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/loop-match/const-continue-to-polymorphic-const.rs b/tests/ui/loop-match/const-continue-to-polymorphic-const.rs new file mode 100644 index 000000000000..9a91c9779111 --- /dev/null +++ b/tests/ui/loop-match/const-continue-to-polymorphic-const.rs @@ -0,0 +1,29 @@ +// Test that a `#[const_continue]` that breaks on a polymorphic constant produces an error. +// A polymorphic constant does not have a concrete value at MIR building time, and therefore the +// `#[loop_match]~ desugaring can't handle such values. +#![allow(incomplete_features)] +#![feature(loop_match)] +#![crate_type = "lib"] + +trait Foo { + const TARGET: u8; + + fn test_u8(mut state: u8) -> &'static str { + #[loop_match] + loop { + state = 'blk: { + match state { + 0 => { + #[const_continue] + break 'blk Self::TARGET; + //~^ ERROR could not determine the target branch for this `#[const_continue]` + } + + 1 => return "bar", + 2 => return "baz", + _ => unreachable!(), + } + } + } + } +} diff --git a/tests/ui/loop-match/const-continue-to-polymorphic-const.stderr b/tests/ui/loop-match/const-continue-to-polymorphic-const.stderr new file mode 100644 index 000000000000..4d183a2fbebc --- /dev/null +++ b/tests/ui/loop-match/const-continue-to-polymorphic-const.stderr @@ -0,0 +1,8 @@ +error: could not determine the target branch for this `#[const_continue]` + --> $DIR/const-continue-to-polymorphic-const.rs:18:36 + | +LL | break 'blk Self::TARGET; + | ^^^^^^^^^^^^ this value is too generic + +error: aborting due to 1 previous error + diff --git a/tests/ui/loop-match/drop-in-match-arm.rs b/tests/ui/loop-match/drop-in-match-arm.rs new file mode 100644 index 000000000000..731af6590129 --- /dev/null +++ b/tests/ui/loop-match/drop-in-match-arm.rs @@ -0,0 +1,47 @@ +// Test that dropping values works in match arms, which is nontrivial +// because each match arm needs its own scope. + +//@ run-pass + +#![allow(incomplete_features)] +#![feature(loop_match)] + +use std::sync::atomic::{AtomicBool, Ordering}; + +fn main() { + assert_eq!(helper(), 1); + assert!(DROPPED.load(Ordering::Relaxed)); +} + +static DROPPED: AtomicBool = AtomicBool::new(false); + +struct X; + +impl Drop for X { + fn drop(&mut self) { + DROPPED.store(true, Ordering::Relaxed); + } +} + +#[no_mangle] +#[inline(never)] +fn helper() -> i32 { + let mut state = 0; + #[loop_match] + 'a: loop { + state = 'blk: { + match state { + 0 => match X { + _ => { + assert!(!DROPPED.load(Ordering::Relaxed)); + break 'blk 1; + } + }, + _ => { + assert!(DROPPED.load(Ordering::Relaxed)); + break 'a state; + } + } + }; + } +} diff --git a/tests/ui/loop-match/invalid-attribute.rs b/tests/ui/loop-match/invalid-attribute.rs new file mode 100644 index 000000000000..d8d2f605eb49 --- /dev/null +++ b/tests/ui/loop-match/invalid-attribute.rs @@ -0,0 +1,43 @@ +// Test that the `#[loop_match]` and `#[const_continue]` attributes can only be +// placed on expressions. + +#![allow(incomplete_features)] +#![feature(loop_match)] +#![loop_match] //~ ERROR should be applied to a loop +#![const_continue] //~ ERROR should be applied to a break expression + +extern "C" { + #[loop_match] //~ ERROR should be applied to a loop + #[const_continue] //~ ERROR should be applied to a break expression + fn f(); +} + +#[loop_match] //~ ERROR should be applied to a loop +#[const_continue] //~ ERROR should be applied to a break expression +#[repr(C)] +struct S { + a: u32, + b: u32, +} + +trait Invoke { + #[loop_match] //~ ERROR should be applied to a loop + #[const_continue] //~ ERROR should be applied to a break expression + extern "C" fn invoke(&self); +} + +#[loop_match] //~ ERROR should be applied to a loop +#[const_continue] //~ ERROR should be applied to a break expression +extern "C" fn ok() {} + +fn main() { + #[loop_match] //~ ERROR should be applied to a loop + #[const_continue] //~ ERROR should be applied to a break expression + || {}; + + { + #[loop_match] //~ ERROR should be applied to a loop + #[const_continue] //~ ERROR should be applied to a break expression + 5 + }; +} diff --git a/tests/ui/loop-match/invalid-attribute.stderr b/tests/ui/loop-match/invalid-attribute.stderr new file mode 100644 index 000000000000..07015311f9c3 --- /dev/null +++ b/tests/ui/loop-match/invalid-attribute.stderr @@ -0,0 +1,131 @@ +error: `#[const_continue]` should be applied to a break expression + --> $DIR/invalid-attribute.rs:16:1 + | +LL | #[const_continue] + | ^^^^^^^^^^^^^^^^^ +LL | #[repr(C)] +LL | struct S { + | -------- not a break expression + +error: `#[loop_match]` should be applied to a loop + --> $DIR/invalid-attribute.rs:15:1 + | +LL | #[loop_match] + | ^^^^^^^^^^^^^ +... +LL | struct S { + | -------- not a loop + +error: `#[const_continue]` should be applied to a break expression + --> $DIR/invalid-attribute.rs:30:1 + | +LL | #[const_continue] + | ^^^^^^^^^^^^^^^^^ +LL | extern "C" fn ok() {} + | ------------------ not a break expression + +error: `#[loop_match]` should be applied to a loop + --> $DIR/invalid-attribute.rs:29:1 + | +LL | #[loop_match] + | ^^^^^^^^^^^^^ +LL | #[const_continue] +LL | extern "C" fn ok() {} + | ------------------ not a loop + +error: `#[const_continue]` should be applied to a break expression + --> $DIR/invalid-attribute.rs:35:5 + | +LL | #[const_continue] + | ^^^^^^^^^^^^^^^^^ +LL | || {}; + | -- not a break expression + +error: `#[loop_match]` should be applied to a loop + --> $DIR/invalid-attribute.rs:34:5 + | +LL | #[loop_match] + | ^^^^^^^^^^^^^ +LL | #[const_continue] +LL | || {}; + | -- not a loop + +error: `#[const_continue]` should be applied to a break expression + --> $DIR/invalid-attribute.rs:40:9 + | +LL | #[const_continue] + | ^^^^^^^^^^^^^^^^^ +LL | 5 + | - not a break expression + +error: `#[loop_match]` should be applied to a loop + --> $DIR/invalid-attribute.rs:39:9 + | +LL | #[loop_match] + | ^^^^^^^^^^^^^ +LL | #[const_continue] +LL | 5 + | - not a loop + +error: `#[const_continue]` should be applied to a break expression + --> $DIR/invalid-attribute.rs:25:5 + | +LL | #[const_continue] + | ^^^^^^^^^^^^^^^^^ +LL | extern "C" fn invoke(&self); + | ---------------------------- not a break expression + +error: `#[loop_match]` should be applied to a loop + --> $DIR/invalid-attribute.rs:24:5 + | +LL | #[loop_match] + | ^^^^^^^^^^^^^ +LL | #[const_continue] +LL | extern "C" fn invoke(&self); + | ---------------------------- not a loop + +error: `#[const_continue]` should be applied to a break expression + --> $DIR/invalid-attribute.rs:11:5 + | +LL | #[const_continue] + | ^^^^^^^^^^^^^^^^^ +LL | fn f(); + | ------- not a break expression + +error: `#[loop_match]` should be applied to a loop + --> $DIR/invalid-attribute.rs:10:5 + | +LL | #[loop_match] + | ^^^^^^^^^^^^^ +LL | #[const_continue] +LL | fn f(); + | ------- not a loop + +error: `#[const_continue]` should be applied to a break expression + --> $DIR/invalid-attribute.rs:7:1 + | +LL | / #![allow(incomplete_features)] +LL | | #![feature(loop_match)] +LL | | #![loop_match] +LL | | #![const_continue] + | | ^^^^^^^^^^^^^^^^^^ +... | +LL | | }; +LL | | } + | |_- not a break expression + +error: `#[loop_match]` should be applied to a loop + --> $DIR/invalid-attribute.rs:6:1 + | +LL | / #![allow(incomplete_features)] +LL | | #![feature(loop_match)] +LL | | #![loop_match] + | | ^^^^^^^^^^^^^^ +LL | | #![const_continue] +... | +LL | | }; +LL | | } + | |_- not a loop + +error: aborting due to 14 previous errors + diff --git a/tests/ui/loop-match/invalid.rs b/tests/ui/loop-match/invalid.rs new file mode 100644 index 000000000000..2ddc19f4fc62 --- /dev/null +++ b/tests/ui/loop-match/invalid.rs @@ -0,0 +1,161 @@ +// Test that the correct error is emitted when `#[loop_match]` is applied to +// syntax it does not support. +#![allow(incomplete_features)] +#![feature(loop_match)] +#![crate_type = "lib"] + +enum State { + A, + B, + C, +} + +fn invalid_update() { + let mut fake = State::A; + let state = State::A; + #[loop_match] + loop { + fake = 'blk: { + //~^ ERROR invalid update of the `#[loop_match]` state + match state { + _ => State::B, + } + } + } +} + +fn invalid_scrutinee() { + let mut state = State::A; + #[loop_match] + loop { + state = 'blk: { + match State::A { + //~^ ERROR invalid match on `#[loop_match]` state + _ => State::B, + } + } + } +} + +fn bad_statements_1() { + let mut state = State::A; + #[loop_match] + loop { + 1; + //~^ ERROR statements are not allowed in this position within a `#[loop_match]` + state = 'blk: { + match State::A { + _ => State::B, + } + } + } +} + +fn bad_statements_2() { + let mut state = State::A; + #[loop_match] + loop { + state = 'blk: { + 1; + //~^ ERROR statements are not allowed in this position within a `#[loop_match]` + match State::A { + _ => State::B, + } + } + } +} + +fn bad_rhs_1() { + let mut state = State::A; + #[loop_match] + loop { + state = State::B + //~^ ERROR this expression must be a single `match` wrapped in a labeled block + } +} + +fn bad_rhs_2() { + let mut state = State::A; + #[loop_match] + loop { + state = 'blk: { + State::B + //~^ ERROR this expression must be a single `match` wrapped in a labeled block + } + } +} + +fn bad_rhs_3() { + let mut state = (); + #[loop_match] + loop { + state = 'blk: { + //~^ ERROR this expression must be a single `match` wrapped in a labeled block + } + } +} + +fn missing_assignment() { + #[loop_match] + loop { + () //~ ERROR expected a single assignment expression + } +} + +fn empty_loop_body() { + #[loop_match] + loop { + //~^ ERROR expected a single assignment expression + } +} + +fn break_without_value() { + let mut state = State::A; + #[loop_match] + 'a: loop { + state = 'blk: { + match state { + State::A => { + #[const_continue] + break 'blk; + //~^ ERROR mismatched types + } + _ => break 'a, + } + } + } +} + +fn break_without_value_unit() { + let mut state = (); + #[loop_match] + 'a: loop { + state = 'blk: { + match state { + () => { + #[const_continue] + break 'blk; + //~^ ERROR a `#[const_continue]` must break to a label with a value + } + } + } + } +} + +fn arm_has_guard(cond: bool) { + let mut state = State::A; + #[loop_match] + 'a: loop { + state = 'blk: { + match state { + State::A => { + #[const_continue] + break 'blk State::B; + } + State::B if cond => break 'a, + //~^ ERROR match arms that are part of a `#[loop_match]` cannot have guards + _ => break 'a, + } + } + } +} diff --git a/tests/ui/loop-match/invalid.stderr b/tests/ui/loop-match/invalid.stderr new file mode 100644 index 000000000000..51fdd024c6fa --- /dev/null +++ b/tests/ui/loop-match/invalid.stderr @@ -0,0 +1,91 @@ +error[E0308]: mismatched types + --> $DIR/invalid.rs:120:21 + | +LL | break 'blk; + | ^^^^^^^^^^ expected `State`, found `()` + | +help: give the `break` a value of the expected type + | +LL | break 'blk /* value */; + | +++++++++++ + +error: invalid update of the `#[loop_match]` state + --> $DIR/invalid.rs:18:9 + | +LL | fake = 'blk: { + | ^^^^ +LL | +LL | match state { + | ----- the assignment must update this variable + +error: invalid match on `#[loop_match]` state + --> $DIR/invalid.rs:32:19 + | +LL | match State::A { + | ^^^^^^^^ + | + = note: a local variable must be the scrutinee within a `#[loop_match]` + +error: statements are not allowed in this position within a `#[loop_match]` + --> $DIR/invalid.rs:44:9 + | +LL | 1; + | ^^ + +error: statements are not allowed in this position within a `#[loop_match]` + --> $DIR/invalid.rs:59:13 + | +LL | 1; + | ^^ + +error: this expression must be a single `match` wrapped in a labeled block + --> $DIR/invalid.rs:72:17 + | +LL | state = State::B + | ^^^^^^^^ + +error: this expression must be a single `match` wrapped in a labeled block + --> $DIR/invalid.rs:82:13 + | +LL | State::B + | ^^^^^^^^ + +error: this expression must be a single `match` wrapped in a labeled block + --> $DIR/invalid.rs:92:17 + | +LL | state = 'blk: { + | _________________^ +LL | | +LL | | } + | |_________^ + +error: expected a single assignment expression + --> $DIR/invalid.rs:101:9 + | +LL | () + | ^^ + +error: expected a single assignment expression + --> $DIR/invalid.rs:107:10 + | +LL | loop { + | __________^ +LL | | +LL | | } + | |_____^ + +error: a `#[const_continue]` must break to a label with a value + --> $DIR/invalid.rs:137:21 + | +LL | break 'blk; + | ^^^^^^^^^^ + +error: match arms that are part of a `#[loop_match]` cannot have guards + --> $DIR/invalid.rs:155:29 + | +LL | State::B if cond => break 'a, + | ^^^^ + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/loop-match/loop-match.rs b/tests/ui/loop-match/loop-match.rs new file mode 100644 index 000000000000..f38bc01f3338 --- /dev/null +++ b/tests/ui/loop-match/loop-match.rs @@ -0,0 +1,45 @@ +// Test that a basic correct example of `#[loop_match]` with `#[const_continue]` +// works correctly. + +//@ run-pass + +#![allow(incomplete_features)] +#![feature(loop_match)] + +enum State { + A, + B, + C, +} + +fn main() { + let mut state = State::A; + #[loop_match] + 'a: loop { + state = 'blk: { + match state { + State::A => { + #[const_continue] + break 'blk State::B; + } + State::B => { + // Without special logic, the compiler believes this is a + // reassignment to an immutable variable because of the + // `loop`. So this tests that local variables work. + let _a = 0; + + if true { + #[const_continue] + break 'blk State::C; + } else { + #[const_continue] + break 'blk State::A; + } + } + State::C => break 'a, + } + }; + } + + assert!(matches!(state, State::C)) +} diff --git a/tests/ui/loop-match/macro.rs b/tests/ui/loop-match/macro.rs new file mode 100644 index 000000000000..98c98b9b627b --- /dev/null +++ b/tests/ui/loop-match/macro.rs @@ -0,0 +1,48 @@ +// Test that macros can be defined in the labeled block. This should not trigger an error about +// statements not being allowed in that position, and should of course work as expected. + +//@ run-pass + +#![allow(incomplete_features)] +#![feature(loop_match)] + +enum State { + A, + B, + C, +} + +fn main() { + let mut state = State::A; + #[loop_match] + 'a: loop { + state = 'blk: { + macro_rules! const_continue { + ($e:expr) => { + #[const_continue] + break 'blk $e; + }; + } + match state { + State::A => { + const_continue!(State::B); + } + State::B => { + // Without special logic, the compiler believes this is a + // reassignment to an immutable variable because of the + // `loop`. So this tests that local variables work. + let _a = 0; + + if true { + const_continue!(State::C); + } else { + const_continue!(State::A); + } + } + State::C => break 'a, + } + }; + } + + assert!(matches!(state, State::C)) +} diff --git a/tests/ui/loop-match/nested.rs b/tests/ui/loop-match/nested.rs new file mode 100644 index 000000000000..aaddfae11def --- /dev/null +++ b/tests/ui/loop-match/nested.rs @@ -0,0 +1,83 @@ +// Test that a nested `#[loop_match]` works as expected, and that e.g. a +// `#[const_continue]` of the inner `#[loop_match]` does not interact with the +// outer `#[loop_match]`. + +//@ run-pass + +#![allow(incomplete_features)] +#![feature(loop_match)] + +enum State1 { + A, + B, + C, +} + +enum State2 { + X, + Y, + Z, +} + +fn main() { + assert_eq!(run(), concat!("ab", "xyz", "xyz", "c")) +} + +fn run() -> String { + let mut accum = String::new(); + + let mut state1 = State1::A; + let mut state2 = State2::X; + + let mut first = true; + + #[loop_match] + 'a: loop { + state1 = 'blk1: { + match state1 { + State1::A => { + accum.push('a'); + #[const_continue] + break 'blk1 State1::B; + } + State1::B => { + accum.push('b'); + #[loop_match] + loop { + state2 = 'blk2: { + match state2 { + State2::X => { + accum.push('x'); + #[const_continue] + break 'blk2 State2::Y; + } + State2::Y => { + accum.push('y'); + #[const_continue] + break 'blk2 State2::Z; + } + State2::Z => { + accum.push('z'); + if first { + first = false; + #[const_continue] + break 'blk2 State2::X; + } else { + #[const_continue] + break 'blk1 State1::C; + } + } + } + } + } + } + State1::C => { + accum.push('c'); + break 'a; + } + } + } + } + + accum +} diff --git a/tests/ui/loop-match/or-patterns.rs b/tests/ui/loop-match/or-patterns.rs new file mode 100644 index 000000000000..775243b9c620 --- /dev/null +++ b/tests/ui/loop-match/or-patterns.rs @@ -0,0 +1,54 @@ +// Test that `#[loop_match]` supports or-patterns. + +//@ run-pass + +#![allow(incomplete_features)] +#![feature(loop_match)] + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum State { + A, + B, + C, + D, +} + +fn main() { + let mut states = vec![]; + let mut first = true; + let mut state = State::A; + #[loop_match] + 'a: loop { + state = 'blk: { + match state { + State::A => { + states.push(state); + if first { + #[const_continue] + break 'blk State::B; + } else { + #[const_continue] + break 'blk State::D; + } + } + State::B | State::D => { + states.push(state); + if first { + first = false; + #[const_continue] + break 'blk State::A; + } else { + #[const_continue] + break 'blk State::C; + } + } + State::C => { + states.push(state); + break 'a; + } + } + } + } + + assert_eq!(states, [State::A, State::B, State::A, State::D, State::C]); +} diff --git a/tests/ui/loop-match/unsupported-type.rs b/tests/ui/loop-match/unsupported-type.rs new file mode 100644 index 000000000000..9100a1103ab7 --- /dev/null +++ b/tests/ui/loop-match/unsupported-type.rs @@ -0,0 +1,27 @@ +// Test that the right error is emitted when the `#[loop_match]` state is an +// unsupported type. + +#![allow(incomplete_features)] +#![feature(loop_match)] +#![crate_type = "lib"] + +fn unsupported_type() { + let mut state = Some(false); + #[loop_match] + 'a: loop { + state = 'blk: { + //~^ ERROR this `#[loop_match]` state value has type `Option`, which is not supported + match state { + Some(false) => { + #[const_continue] + break 'blk Some(true); + } + Some(true) => { + #[const_continue] + break 'blk None; + } + None => break 'a, + } + } + } +} diff --git a/tests/ui/loop-match/unsupported-type.stderr b/tests/ui/loop-match/unsupported-type.stderr new file mode 100644 index 000000000000..ede3d86796fd --- /dev/null +++ b/tests/ui/loop-match/unsupported-type.stderr @@ -0,0 +1,10 @@ +error: this `#[loop_match]` state value has type `Option`, which is not supported + --> $DIR/unsupported-type.rs:12:9 + | +LL | state = 'blk: { + | ^^^^^ + | + = note: only integers, floats, bool, char, and enums without fields are supported + +error: aborting due to 1 previous error + diff --git a/tests/ui/loop-match/unwind.rs b/tests/ui/loop-match/unwind.rs new file mode 100644 index 000000000000..39e2e4537b17 --- /dev/null +++ b/tests/ui/loop-match/unwind.rs @@ -0,0 +1,53 @@ +// Test that `#[const_continue]` correctly emits cleanup paths for drops. +// +// Here, we first drop `DropBomb`, causing an unwind. Then `ExitOnDrop` should +// be dropped, causing us to exit with `0` rather than with some non-zero value +// due to the panic, which is what causes the test to pass. + +//@ run-pass +//@ needs-unwind + +#![allow(incomplete_features)] +#![feature(loop_match)] + +enum State { + A, + B, +} + +struct ExitOnDrop; + +impl Drop for ExitOnDrop { + fn drop(&mut self) { + std::process::exit(0); + } +} + +struct DropBomb; + +impl Drop for DropBomb { + fn drop(&mut self) { + panic!("this must unwind"); + } +} + +fn main() { + let mut state = State::A; + #[loop_match] + 'a: loop { + state = 'blk: { + match state { + State::A => { + let _exit = ExitOnDrop; + let _bomb = DropBomb; + + #[const_continue] + break 'blk State::B; + } + State::B => break 'a, + } + }; + } + + unreachable!(); +} diff --git a/tests/ui/loop-match/valid-patterns.rs b/tests/ui/loop-match/valid-patterns.rs new file mode 100644 index 000000000000..4e0e4798a0bd --- /dev/null +++ b/tests/ui/loop-match/valid-patterns.rs @@ -0,0 +1,117 @@ +// Test that signed and unsigned integer patterns work with `#[loop_match]`. + +//@ run-pass + +#![allow(incomplete_features)] +#![feature(loop_match)] + +fn main() { + assert_eq!(integer(0), 2); + assert_eq!(integer(-1), 2); + assert_eq!(integer(2), 2); + + assert_eq!(boolean(true), false); + assert_eq!(boolean(false), false); + + assert_eq!(character('a'), 'b'); + assert_eq!(character('b'), 'b'); + assert_eq!(character('c'), 'd'); + assert_eq!(character('d'), 'd'); + + assert_eq!(test_f32(1.0), core::f32::consts::PI); + assert_eq!(test_f32(2.5), core::f32::consts::PI); + assert_eq!(test_f32(4.0), 4.0); + + assert_eq!(test_f64(1.0), core::f64::consts::PI); + assert_eq!(test_f64(2.5), core::f64::consts::PI); + assert_eq!(test_f64(4.0), 4.0); +} + +fn integer(mut state: i32) -> i32 { + #[loop_match] + 'a: loop { + state = 'blk: { + match state { + -1 => { + #[const_continue] + break 'blk 2; + } + 0 => { + #[const_continue] + break 'blk -1; + } + 2 => break 'a, + _ => unreachable!("weird value {:?}", state), + } + } + } + + state +} + +fn boolean(mut state: bool) -> bool { + #[loop_match] + loop { + state = 'blk: { + match state { + true => { + #[const_continue] + break 'blk false; + } + false => return state, + } + } + } +} + +fn character(mut state: char) -> char { + #[loop_match] + loop { + state = 'blk: { + match state { + 'a' => { + #[const_continue] + break 'blk 'b'; + } + 'b' => return state, + 'c' => { + #[const_continue] + break 'blk 'd'; + } + _ => return state, + } + } + } +} + +fn test_f32(mut state: f32) -> f32 { + #[loop_match] + loop { + state = 'blk: { + match state { + 1.0 => { + #[const_continue] + break 'blk 2.5; + } + 2.0..3.0 => return core::f32::consts::PI, + _ => return state, + } + } + } +} + +fn test_f64(mut state: f64) -> f64 { + #[loop_match] + loop { + state = 'blk: { + match state { + 1.0 => { + #[const_continue] + break 'blk 2.5; + } + 2.0..3.0 => return core::f64::consts::PI, + _ => return state, + } + } + } +} diff --git a/tests/ui/macros/concat-bytes-error.rs b/tests/ui/macros/concat-bytes-error.rs index db5d3cab0bd8..8130fc54d8d5 100644 --- a/tests/ui/macros/concat-bytes-error.rs +++ b/tests/ui/macros/concat-bytes-error.rs @@ -1,20 +1,44 @@ +//@ edition: 2021 +// 2021 edition for C string literals + #![feature(concat_bytes)] fn main() { + // Identifiers concat_bytes!(pie); //~ ERROR expected a byte literal concat_bytes!(pie, pie); //~ ERROR expected a byte literal + + // String literals concat_bytes!("tnrsi", "tnri"); //~ ERROR cannot concatenate string literals + //~^ SUGGESTION b"tnrsi" + concat_bytes!(r"tnrsi", r"tnri"); //~ ERROR cannot concatenate string literals + //~^ SUGGESTION br"tnrsi" + concat_bytes!(r#"tnrsi"#, r###"tnri"###); //~ ERROR cannot concatenate string literals + //~^ SUGGESTION br#"tnrsi"# + concat_bytes!(c"tnrsi", c"tnri"); //~ ERROR cannot concatenate C string literals + //~^ SUGGESTION b"tnrsi\0" + concat_bytes!(cr"tnrsi", cr"tnri"); //~ ERROR cannot concatenate C string literals + concat_bytes!(cr#"tnrsi"#, cr###"tnri"###); //~ ERROR cannot concatenate C string literals + + // Other literals concat_bytes!(2.8); //~ ERROR cannot concatenate float literals concat_bytes!(300); //~ ERROR cannot concatenate numeric literals + //~^ SUGGESTION [300] concat_bytes!('a'); //~ ERROR cannot concatenate character literals + //~^ SUGGESTION b'a' concat_bytes!(true, false); //~ ERROR cannot concatenate boolean literals concat_bytes!(42, b"va", b'l'); //~ ERROR cannot concatenate numeric literals + //~^ SUGGESTION [42] concat_bytes!(42, b"va", b'l', [1, 2]); //~ ERROR cannot concatenate numeric literals + //~^ SUGGESTION [42] + + // Nested items concat_bytes!([ "hi", //~ ERROR cannot concatenate string literals ]); concat_bytes!([ 'a', //~ ERROR cannot concatenate character literals + //~^ SUGGESTION b'a' ]); concat_bytes!([ true, //~ ERROR cannot concatenate boolean literals @@ -38,6 +62,7 @@ fn main() { [5, 6, 7], //~ ERROR cannot concatenate doubly nested array ]); concat_bytes!(5u16); //~ ERROR cannot concatenate numeric literals + //~^ SUGGESTION [5u16] concat_bytes!([5u16]); //~ ERROR numeric literal is not a `u8` concat_bytes!([3; ()]); //~ ERROR repeat count is not a positive number concat_bytes!([3; -2]); //~ ERROR repeat count is not a positive number diff --git a/tests/ui/macros/concat-bytes-error.stderr b/tests/ui/macros/concat-bytes-error.stderr index 3f2c64922e34..447d7a663fdc 100644 --- a/tests/ui/macros/concat-bytes-error.stderr +++ b/tests/ui/macros/concat-bytes-error.stderr @@ -1,5 +1,5 @@ error: expected a byte literal - --> $DIR/concat-bytes-error.rs:4:19 + --> $DIR/concat-bytes-error.rs:8:19 | LL | concat_bytes!(pie); | ^^^ @@ -7,7 +7,7 @@ LL | concat_bytes!(pie); = note: only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()` error: expected a byte literal - --> $DIR/concat-bytes-error.rs:5:19 + --> $DIR/concat-bytes-error.rs:9:19 | LL | concat_bytes!(pie, pie); | ^^^ ^^^ @@ -15,85 +15,126 @@ LL | concat_bytes!(pie, pie); = note: only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()` error: cannot concatenate string literals - --> $DIR/concat-bytes-error.rs:6:19 + --> $DIR/concat-bytes-error.rs:12:19 | LL | concat_bytes!("tnrsi", "tnri"); | ^^^^^^^ help: try using a byte string: `b"tnrsi"` +error: cannot concatenate string literals + --> $DIR/concat-bytes-error.rs:14:19 + | +LL | concat_bytes!(r"tnrsi", r"tnri"); + | ^^^^^^^^ help: try using a byte string: `br"tnrsi"` + +error: cannot concatenate string literals + --> $DIR/concat-bytes-error.rs:16:19 + | +LL | concat_bytes!(r#"tnrsi"#, r###"tnri"###); + | ^^^^^^^^^^ help: try using a byte string: `br#"tnrsi"#` + +error: cannot concatenate C string literals + --> $DIR/concat-bytes-error.rs:18:19 + | +LL | concat_bytes!(c"tnrsi", c"tnri"); + | ^^^^^^^^ help: try using a null-terminated byte string: `b"tnrsi\0"` + | +note: concatenating C strings is ambiguous about including the '\0' + --> $DIR/concat-bytes-error.rs:18:19 + | +LL | concat_bytes!(c"tnrsi", c"tnri"); + | ^^^^^^^^ + = note: concatenating C strings is ambiguous about including the '\0' + +error: cannot concatenate C string literals + --> $DIR/concat-bytes-error.rs:20:19 + | +LL | concat_bytes!(cr"tnrsi", cr"tnri"); + | ^^^^^^^^^ + | + = note: concatenating C strings is ambiguous about including the '\0' + +error: cannot concatenate C string literals + --> $DIR/concat-bytes-error.rs:21:19 + | +LL | concat_bytes!(cr#"tnrsi"#, cr###"tnri"###); + | ^^^^^^^^^^^ + | + = note: concatenating C strings is ambiguous about including the '\0' + error: cannot concatenate float literals - --> $DIR/concat-bytes-error.rs:7:19 + --> $DIR/concat-bytes-error.rs:24:19 | LL | concat_bytes!(2.8); | ^^^ error: cannot concatenate numeric literals - --> $DIR/concat-bytes-error.rs:8:19 + --> $DIR/concat-bytes-error.rs:25:19 | LL | concat_bytes!(300); | ^^^ help: try wrapping the number in an array: `[300]` error: cannot concatenate character literals - --> $DIR/concat-bytes-error.rs:9:19 + --> $DIR/concat-bytes-error.rs:27:19 | LL | concat_bytes!('a'); | ^^^ help: try using a byte character: `b'a'` error: cannot concatenate boolean literals - --> $DIR/concat-bytes-error.rs:10:19 + --> $DIR/concat-bytes-error.rs:29:19 | LL | concat_bytes!(true, false); | ^^^^ error: cannot concatenate numeric literals - --> $DIR/concat-bytes-error.rs:11:19 + --> $DIR/concat-bytes-error.rs:30:19 | LL | concat_bytes!(42, b"va", b'l'); | ^^ help: try wrapping the number in an array: `[42]` error: cannot concatenate numeric literals - --> $DIR/concat-bytes-error.rs:12:19 + --> $DIR/concat-bytes-error.rs:32:19 | LL | concat_bytes!(42, b"va", b'l', [1, 2]); | ^^ help: try wrapping the number in an array: `[42]` error: cannot concatenate string literals - --> $DIR/concat-bytes-error.rs:14:9 + --> $DIR/concat-bytes-error.rs:37:9 | LL | "hi", | ^^^^ error: cannot concatenate character literals - --> $DIR/concat-bytes-error.rs:17:9 + --> $DIR/concat-bytes-error.rs:40:9 | LL | 'a', | ^^^ help: try using a byte character: `b'a'` error: cannot concatenate boolean literals - --> $DIR/concat-bytes-error.rs:20:9 + --> $DIR/concat-bytes-error.rs:44:9 | LL | true, | ^^^^ error: cannot concatenate boolean literals - --> $DIR/concat-bytes-error.rs:23:9 + --> $DIR/concat-bytes-error.rs:47:9 | LL | false, | ^^^^^ error: cannot concatenate float literals - --> $DIR/concat-bytes-error.rs:26:9 + --> $DIR/concat-bytes-error.rs:50:9 | LL | 2.6, | ^^^ error: numeric literal is out of bounds - --> $DIR/concat-bytes-error.rs:29:9 + --> $DIR/concat-bytes-error.rs:53:9 | LL | 265, | ^^^ error: expected a byte literal - --> $DIR/concat-bytes-error.rs:32:9 + --> $DIR/concat-bytes-error.rs:56:9 | LL | -33, | ^^^ @@ -101,7 +142,7 @@ LL | -33, = note: only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()` error: cannot concatenate doubly nested array - --> $DIR/concat-bytes-error.rs:35:9 + --> $DIR/concat-bytes-error.rs:59:9 | LL | b"hi!", | ^^^^^^ @@ -110,43 +151,43 @@ LL | b"hi!", = help: try flattening the array error: cannot concatenate doubly nested array - --> $DIR/concat-bytes-error.rs:38:9 + --> $DIR/concat-bytes-error.rs:62:9 | LL | [5, 6, 7], | ^^^^^^^^^ error: cannot concatenate numeric literals - --> $DIR/concat-bytes-error.rs:40:19 + --> $DIR/concat-bytes-error.rs:64:19 | LL | concat_bytes!(5u16); | ^^^^ help: try wrapping the number in an array: `[5u16]` error: numeric literal is not a `u8` - --> $DIR/concat-bytes-error.rs:41:20 + --> $DIR/concat-bytes-error.rs:66:20 | LL | concat_bytes!([5u16]); | ^^^^ error: repeat count is not a positive number - --> $DIR/concat-bytes-error.rs:42:23 + --> $DIR/concat-bytes-error.rs:67:23 | LL | concat_bytes!([3; ()]); | ^^ error: repeat count is not a positive number - --> $DIR/concat-bytes-error.rs:43:23 + --> $DIR/concat-bytes-error.rs:68:23 | LL | concat_bytes!([3; -2]); | ^^ error: repeat count is not a positive number - --> $DIR/concat-bytes-error.rs:44:25 + --> $DIR/concat-bytes-error.rs:69:25 | LL | concat_bytes!([pie; -2]); | ^^ error: expected a byte literal - --> $DIR/concat-bytes-error.rs:45:20 + --> $DIR/concat-bytes-error.rs:70:20 | LL | concat_bytes!([pie; 2]); | ^^^ @@ -154,28 +195,28 @@ LL | concat_bytes!([pie; 2]); = note: only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()` error: cannot concatenate float literals - --> $DIR/concat-bytes-error.rs:46:20 + --> $DIR/concat-bytes-error.rs:71:20 | LL | concat_bytes!([2.2; 0]); | ^^^ error: repeat count is not a positive number - --> $DIR/concat-bytes-error.rs:47:25 + --> $DIR/concat-bytes-error.rs:72:25 | LL | concat_bytes!([5.5; ()]); | ^^ error: cannot concatenate doubly nested array - --> $DIR/concat-bytes-error.rs:48:20 + --> $DIR/concat-bytes-error.rs:73:20 | LL | concat_bytes!([[1, 2, 3]; 3]); | ^^^^^^^^^ error: cannot concatenate doubly nested array - --> $DIR/concat-bytes-error.rs:49:20 + --> $DIR/concat-bytes-error.rs:74:20 | LL | concat_bytes!([[42; 2]; 3]); | ^^^^^^^ -error: aborting due to 28 previous errors +error: aborting due to 33 previous errors diff --git a/tests/ui/macros/format-args-temporaries-in-write.stderr b/tests/ui/macros/format-args-temporaries-in-write.stderr index e58a43383f6e..489987899cd7 100644 --- a/tests/ui/macros/format-args-temporaries-in-write.stderr +++ b/tests/ui/macros/format-args-temporaries-in-write.stderr @@ -13,11 +13,6 @@ LL | }; | -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard` | | | `mutex` dropped here while still borrowed - | -help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped - | -LL | write!(Out, "{}", mutex.lock()); /* no semicolon */ - | + error[E0597]: `mutex` does not live long enough --> $DIR/format-args-temporaries-in-write.rs:47:29 @@ -34,11 +29,6 @@ LL | }; | -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard` | | | `mutex` dropped here while still borrowed - | -help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped - | -LL | writeln!(Out, "{}", mutex.lock()); /* no semicolon */ - | + error: aborting due to 2 previous errors diff --git a/tests/ui/macros/macro-comma-support-rpass.rs b/tests/ui/macros/macro-comma-support-rpass.rs index 5a4bac70b1ce..ef6c1ff6fd06 100644 --- a/tests/ui/macros/macro-comma-support-rpass.rs +++ b/tests/ui/macros/macro-comma-support-rpass.rs @@ -15,7 +15,6 @@ #![cfg_attr(core, no_std)] #![allow(deprecated)] // for deprecated `try!()` macro -#![feature(concat_idents)] #[cfg(std)] use std::fmt; #[cfg(core)] use core::fmt; @@ -79,17 +78,6 @@ fn concat() { let _ = concat!("hello", " world",); } -#[test] -fn concat_idents() { - fn foo() {} - fn foobar() {} - - concat_idents!(foo)(); - concat_idents!(foo,)(); - concat_idents!(foo, bar)(); - concat_idents!(foo, bar,)(); -} - #[test] fn debug_assert() { debug_assert!(true); diff --git a/tests/ui/macros/macro-match-nonterminal.rs b/tests/ui/macros/macro-match-nonterminal.rs index fa2af945a1f1..1643cddb192b 100644 --- a/tests/ui/macros/macro-match-nonterminal.rs +++ b/tests/ui/macros/macro-match-nonterminal.rs @@ -2,11 +2,10 @@ macro_rules! test { ($a, $b) => { //~^ ERROR missing fragment //~| ERROR missing fragment - //~| ERROR missing fragment () }; } fn main() { - test!() + test!() //~ ERROR unexpected end of macro invocation } diff --git a/tests/ui/macros/macro-match-nonterminal.stderr b/tests/ui/macros/macro-match-nonterminal.stderr index 8196d795c4c8..a92d099ca008 100644 --- a/tests/ui/macros/macro-match-nonterminal.stderr +++ b/tests/ui/macros/macro-match-nonterminal.stderr @@ -24,7 +24,16 @@ help: try adding a specifier here LL | ($a, $b:spec) => { | +++++ -error: missing fragment specifier +error: unexpected end of macro invocation + --> $DIR/macro-match-nonterminal.rs:10:5 + | +LL | macro_rules! test { + | ----------------- when calling this macro +... +LL | test!() + | ^^^^^^^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$a:tt` --> $DIR/macro-match-nonterminal.rs:2:6 | LL | ($a, $b) => { diff --git a/tests/ui/macros/macro-metavar-expr-concat/empty-input.rs b/tests/ui/macros/macro-metavar-expr-concat/empty-input.rs new file mode 100644 index 000000000000..caad63c5f6b0 --- /dev/null +++ b/tests/ui/macros/macro-metavar-expr-concat/empty-input.rs @@ -0,0 +1,12 @@ +// Issue 50403 +// Ensure that `concat` can't create empty identifiers +// FIXME(macro_metavar_expr_concat): this error message could be improved + +macro_rules! empty { + () => { ${concat()} } //~ ERROR expected identifier or string literal + //~^ERROR expected expression +} + +fn main() { + let x = empty!(); +} diff --git a/tests/ui/macros/macro-metavar-expr-concat/empty-input.stderr b/tests/ui/macros/macro-metavar-expr-concat/empty-input.stderr new file mode 100644 index 000000000000..e95032dd2478 --- /dev/null +++ b/tests/ui/macros/macro-metavar-expr-concat/empty-input.stderr @@ -0,0 +1,19 @@ +error: expected identifier or string literal + --> $DIR/empty-input.rs:6:14 + | +LL | () => { ${concat()} } + | ^^^^^^^^^^ + +error: expected expression, found `$` + --> $DIR/empty-input.rs:6:13 + | +LL | () => { ${concat()} } + | ^ expected expression +... +LL | let x = empty!(); + | -------- in this macro invocation + | + = note: this error originates in the macro `empty` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/macro-missing-fragment-deduplication.rs b/tests/ui/macros/macro-missing-fragment-deduplication.rs index 481f08fa1119..fc81c713b4d5 100644 --- a/tests/ui/macros/macro-missing-fragment-deduplication.rs +++ b/tests/ui/macros/macro-missing-fragment-deduplication.rs @@ -2,12 +2,11 @@ macro_rules! m { ($name) => {}; //~ ERROR missing fragment - //~| ERROR missing fragment } fn main() { - m!(); - m!(); - m!(); - m!(); + m!(); //~ ERROR unexpected end + m!(); //~ ERROR unexpected end + m!(); //~ ERROR unexpected end + m!(); //~ ERROR unexpected end } diff --git a/tests/ui/macros/macro-missing-fragment-deduplication.stderr b/tests/ui/macros/macro-missing-fragment-deduplication.stderr index 820f7eb3cf7f..29d2ae0e16ed 100644 --- a/tests/ui/macros/macro-missing-fragment-deduplication.stderr +++ b/tests/ui/macros/macro-missing-fragment-deduplication.stderr @@ -11,11 +11,65 @@ help: try adding a specifier here LL | ($name:spec) => {}; | +++++ -error: missing fragment specifier +error: unexpected end of macro invocation + --> $DIR/macro-missing-fragment-deduplication.rs:8:5 + | +LL | macro_rules! m { + | -------------- when calling this macro +... +LL | m!(); + | ^^^^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$name:tt` --> $DIR/macro-missing-fragment-deduplication.rs:4:6 | LL | ($name) => {}; | ^^^^^ -error: aborting due to 2 previous errors +error: unexpected end of macro invocation + --> $DIR/macro-missing-fragment-deduplication.rs:9:5 + | +LL | macro_rules! m { + | -------------- when calling this macro +... +LL | m!(); + | ^^^^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$name:tt` + --> $DIR/macro-missing-fragment-deduplication.rs:4:6 + | +LL | ($name) => {}; + | ^^^^^ + +error: unexpected end of macro invocation + --> $DIR/macro-missing-fragment-deduplication.rs:10:5 + | +LL | macro_rules! m { + | -------------- when calling this macro +... +LL | m!(); + | ^^^^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$name:tt` + --> $DIR/macro-missing-fragment-deduplication.rs:4:6 + | +LL | ($name) => {}; + | ^^^^^ + +error: unexpected end of macro invocation + --> $DIR/macro-missing-fragment-deduplication.rs:11:5 + | +LL | macro_rules! m { + | -------------- when calling this macro +... +LL | m!(); + | ^^^^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$name:tt` + --> $DIR/macro-missing-fragment-deduplication.rs:4:6 + | +LL | ($name) => {}; + | ^^^^^ + +error: aborting due to 5 previous errors diff --git a/tests/ui/macros/macro-missing-fragment.rs b/tests/ui/macros/macro-missing-fragment.rs index 533aa147bcbf..7ed9074020e4 100644 --- a/tests/ui/macros/macro-missing-fragment.rs +++ b/tests/ui/macros/macro-missing-fragment.rs @@ -2,7 +2,6 @@ macro_rules! used_arm { ( $( any_token $field_rust_type )* ) => {}; //~ ERROR missing fragment - //~| ERROR missing fragment } macro_rules! used_macro_unused_arm { diff --git a/tests/ui/macros/macro-missing-fragment.stderr b/tests/ui/macros/macro-missing-fragment.stderr index 4a99d7d949cf..886292378d1a 100644 --- a/tests/ui/macros/macro-missing-fragment.stderr +++ b/tests/ui/macros/macro-missing-fragment.stderr @@ -12,7 +12,7 @@ LL | ( $( any_token $field_rust_type:spec )* ) => {}; | +++++ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:10:7 + --> $DIR/macro-missing-fragment.rs:9:7 | LL | ( $name ) => {}; | ^^^^^ @@ -25,7 +25,7 @@ LL | ( $name:spec ) => {}; | +++++ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:14:7 + --> $DIR/macro-missing-fragment.rs:13:7 | LL | ( $name ) => {}; | ^^^^^ @@ -37,11 +37,5 @@ help: try adding a specifier here LL | ( $name:spec ) => {}; | +++++ -error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:4:20 - | -LL | ( $( any_token $field_rust_type )* ) => {}; - | ^^^^^^^^^^^^^^^^ - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/macros/macro-reexport-removed.rs b/tests/ui/macros/macro-reexport-removed.rs index c1267f14cd86..4a054686d776 100644 --- a/tests/ui/macros/macro-reexport-removed.rs +++ b/tests/ui/macros/macro-reexport-removed.rs @@ -1,5 +1,4 @@ //@ aux-build:two_macros.rs -//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION" #![feature(macro_reexport)] //~ ERROR feature has been removed diff --git a/tests/ui/macros/macro-reexport-removed.stderr b/tests/ui/macros/macro-reexport-removed.stderr index d4940eeb7755..8130fe0c4bda 100644 --- a/tests/ui/macros/macro-reexport-removed.stderr +++ b/tests/ui/macros/macro-reexport-removed.stderr @@ -1,14 +1,14 @@ error[E0557]: feature has been removed - --> $DIR/macro-reexport-removed.rs:4:12 + --> $DIR/macro-reexport-removed.rs:3:12 | LL | #![feature(macro_reexport)] | ^^^^^^^^^^^^^^ feature has been removed | - = note: removed in 1.0.0 (you are using $RUSTC_VERSION); see for more information + = note: removed in 1.0.0; see for more information = note: subsumed by `pub use` error: cannot find attribute `macro_reexport` in this scope - --> $DIR/macro-reexport-removed.rs:6:3 + --> $DIR/macro-reexport-removed.rs:5:3 | LL | #[macro_reexport(macro_one)] | ^^^^^^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_export` diff --git a/tests/ui/macros/macros-nonfatal-errors.rs b/tests/ui/macros/macros-nonfatal-errors.rs index 091d64ea5d9e..1349d7415105 100644 --- a/tests/ui/macros/macros-nonfatal-errors.rs +++ b/tests/ui/macros/macros-nonfatal-errors.rs @@ -3,9 +3,8 @@ // test that errors in a (selection) of macros don't kill compilation // immediately, so that we get more errors listed at a time. -#![feature(trace_macros, concat_idents)] +#![feature(trace_macros)] #![feature(stmt_expr_attributes)] -#![expect(deprecated)] // concat_idents is deprecated use std::arch::asm; @@ -105,8 +104,6 @@ fn main() { asm!(invalid); //~ ERROR llvm_asm!(invalid); //~ ERROR - concat_idents!("not", "idents"); //~ ERROR - option_env!(invalid); //~ ERROR env!(invalid); //~ ERROR env!(foo, abr, baz); //~ ERROR diff --git a/tests/ui/macros/macros-nonfatal-errors.stderr b/tests/ui/macros/macros-nonfatal-errors.stderr index 2f990cb24e2b..bc34bd1c8ec8 100644 --- a/tests/ui/macros/macros-nonfatal-errors.stderr +++ b/tests/ui/macros/macros-nonfatal-errors.stderr @@ -1,5 +1,5 @@ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:14:5 + --> $DIR/macros-nonfatal-errors.rs:13:5 | LL | #[default] | ^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[default] = help: consider a manual implementation of `Default` error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:19:36 + --> $DIR/macros-nonfatal-errors.rs:18:36 | LL | struct DefaultInnerAttrTupleStruct(#[default] ()); | ^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | struct DefaultInnerAttrTupleStruct(#[default] ()); = help: consider a manual implementation of `Default` error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:23:1 + --> $DIR/macros-nonfatal-errors.rs:22:1 | LL | #[default] | ^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | #[default] = help: consider a manual implementation of `Default` error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:27:1 + --> $DIR/macros-nonfatal-errors.rs:26:1 | LL | #[default] | ^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | #[default] = help: consider a manual implementation of `Default` error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:37:11 + --> $DIR/macros-nonfatal-errors.rs:36:11 | LL | Foo = #[default] 0, | ^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | Foo = #[default] 0, = help: consider a manual implementation of `Default` error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:38:14 + --> $DIR/macros-nonfatal-errors.rs:37:14 | LL | Bar([u8; #[default] 1]), | ^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | Bar([u8; #[default] 1]), = help: consider a manual implementation of `Default` error[E0665]: `#[derive(Default)]` on enum with no `#[default]` - --> $DIR/macros-nonfatal-errors.rs:43:10 + --> $DIR/macros-nonfatal-errors.rs:42:10 | LL | #[derive(Default)] | ^^^^^^^ @@ -67,7 +67,7 @@ LL | #[default] Bar, | ++++++++++ error[E0665]: `#[derive(Default)]` on enum with no `#[default]` - --> $DIR/macros-nonfatal-errors.rs:49:10 + --> $DIR/macros-nonfatal-errors.rs:48:10 | LL | #[derive(Default)] | ^^^^^^^ @@ -78,7 +78,7 @@ LL | | } | |_- this enum needs a unit variant marked with `#[default]` error: multiple declared defaults - --> $DIR/macros-nonfatal-errors.rs:55:10 + --> $DIR/macros-nonfatal-errors.rs:54:10 | LL | #[derive(Default)] | ^^^^^^^ @@ -95,7 +95,7 @@ LL | Baz, = note: only one variant can be default error: `#[default]` attribute does not accept a value - --> $DIR/macros-nonfatal-errors.rs:67:5 + --> $DIR/macros-nonfatal-errors.rs:66:5 | LL | #[default = 1] | ^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | #[default = 1] = help: try using `#[default]` error: multiple `#[default]` attributes - --> $DIR/macros-nonfatal-errors.rs:75:5 + --> $DIR/macros-nonfatal-errors.rs:74:5 | LL | #[default] | ---------- `#[default]` used here @@ -114,13 +114,13 @@ LL | Foo, | = note: only one `#[default]` attribute is needed help: try removing this - --> $DIR/macros-nonfatal-errors.rs:74:5 + --> $DIR/macros-nonfatal-errors.rs:73:5 | LL | #[default] | ^^^^^^^^^^ error: multiple `#[default]` attributes - --> $DIR/macros-nonfatal-errors.rs:85:5 + --> $DIR/macros-nonfatal-errors.rs:84:5 | LL | #[default] | ---------- `#[default]` used here @@ -132,7 +132,7 @@ LL | Foo, | = note: only one `#[default]` attribute is needed help: try removing these - --> $DIR/macros-nonfatal-errors.rs:82:5 + --> $DIR/macros-nonfatal-errors.rs:81:5 | LL | #[default] | ^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | #[default] | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:92:5 + --> $DIR/macros-nonfatal-errors.rs:91:5 | LL | Foo {}, | ^^^ @@ -150,7 +150,7 @@ LL | Foo {}, = help: consider a manual implementation of `Default` error: default variant must be exhaustive - --> $DIR/macros-nonfatal-errors.rs:100:5 + --> $DIR/macros-nonfatal-errors.rs:99:5 | LL | #[non_exhaustive] | ----------------- declared `#[non_exhaustive]` here @@ -160,37 +160,31 @@ LL | Foo, = help: consider a manual implementation of `Default` error: asm template must be a string literal - --> $DIR/macros-nonfatal-errors.rs:105:10 + --> $DIR/macros-nonfatal-errors.rs:104:10 | LL | asm!(invalid); | ^^^^^^^ -error: `concat_idents!()` requires ident args - --> $DIR/macros-nonfatal-errors.rs:108:5 - | -LL | concat_idents!("not", "idents"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:110:17 + --> $DIR/macros-nonfatal-errors.rs:107:17 | LL | option_env!(invalid); | ^^^^^^^ error: expected string literal - --> $DIR/macros-nonfatal-errors.rs:111:10 + --> $DIR/macros-nonfatal-errors.rs:108:10 | LL | env!(invalid); | ^^^^^^^ error: `env!()` takes 1 or 2 arguments - --> $DIR/macros-nonfatal-errors.rs:112:5 + --> $DIR/macros-nonfatal-errors.rs:109:5 | LL | env!(foo, abr, baz); | ^^^^^^^^^^^^^^^^^^^ error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined at compile time - --> $DIR/macros-nonfatal-errors.rs:113:5 + --> $DIR/macros-nonfatal-errors.rs:110:5 | LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -198,7 +192,7 @@ LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); = help: use `std::env::var("RUST_HOPEFULLY_THIS_DOESNT_EXIST")` to read the variable at run time error: format argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:115:13 + --> $DIR/macros-nonfatal-errors.rs:112:13 | LL | format!(invalid); | ^^^^^^^ @@ -209,43 +203,43 @@ LL | format!("{}", invalid); | +++++ error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:117:14 + --> $DIR/macros-nonfatal-errors.rs:114:14 | LL | include!(invalid); | ^^^^^^^ error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:119:18 + --> $DIR/macros-nonfatal-errors.rs:116:18 | LL | include_str!(invalid); | ^^^^^^^ error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG - --> $DIR/macros-nonfatal-errors.rs:120:5 + --> $DIR/macros-nonfatal-errors.rs:117:5 | LL | include_str!("i'd be quite surprised if a file with this name existed"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:121:20 + --> $DIR/macros-nonfatal-errors.rs:118:20 | LL | include_bytes!(invalid); | ^^^^^^^ error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG - --> $DIR/macros-nonfatal-errors.rs:122:5 + --> $DIR/macros-nonfatal-errors.rs:119:5 | LL | include_bytes!("i'd be quite surprised if a file with this name existed"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trace_macros! accepts only `true` or `false` - --> $DIR/macros-nonfatal-errors.rs:124:5 + --> $DIR/macros-nonfatal-errors.rs:121:5 | LL | trace_macros!(invalid); | ^^^^^^^^^^^^^^^^^^^^^^ error: default variant must be exhaustive - --> $DIR/macros-nonfatal-errors.rs:134:9 + --> $DIR/macros-nonfatal-errors.rs:131:9 | LL | #[non_exhaustive] | ----------------- declared `#[non_exhaustive]` here @@ -255,11 +249,11 @@ LL | Foo, = help: consider a manual implementation of `Default` error: cannot find macro `llvm_asm` in this scope - --> $DIR/macros-nonfatal-errors.rs:106:5 + --> $DIR/macros-nonfatal-errors.rs:105:5 | LL | llvm_asm!(invalid); | ^^^^^^^^ -error: aborting due to 29 previous errors +error: aborting due to 28 previous errors For more information about this error, try `rustc --explain E0665`. diff --git a/tests/ui/macros/missing-writer-issue-139830.rs b/tests/ui/macros/missing-writer-issue-139830.rs new file mode 100644 index 000000000000..da4608776c31 --- /dev/null +++ b/tests/ui/macros/missing-writer-issue-139830.rs @@ -0,0 +1,9 @@ +// Make sure we don't suggest a method change inside the `write!` macro. +// +// See + +fn main() { + let mut buf = String::new(); + let _ = write!(buf, "foo"); + //~^ ERROR cannot write into `String` +} diff --git a/tests/ui/macros/missing-writer-issue-139830.stderr b/tests/ui/macros/missing-writer-issue-139830.stderr new file mode 100644 index 000000000000..34dd61328e00 --- /dev/null +++ b/tests/ui/macros/missing-writer-issue-139830.stderr @@ -0,0 +1,23 @@ +error[E0599]: cannot write into `String` + --> $DIR/missing-writer-issue-139830.rs:7:20 + | +LL | let _ = write!(buf, "foo"); + | ^^^ + --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL + | + = note: the method is available for `String` here + | +note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method + --> $DIR/missing-writer-issue-139830.rs:7:20 + | +LL | let _ = write!(buf, "foo"); + | ^^^ + = help: items from traits can only be used if the trait is in scope +help: trait `Write` which provides `write_fmt` is implemented but not in scope; perhaps you want to import it + | +LL + use std::fmt::Write; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/methods/suggest-convert-ptr-to-ref.stderr b/tests/ui/methods/suggest-convert-ptr-to-ref.stderr index 7d52b20121e9..8cb97ea458bc 100644 --- a/tests/ui/methods/suggest-convert-ptr-to-ref.stderr +++ b/tests/ui/methods/suggest-convert-ptr-to-ref.stderr @@ -2,7 +2,7 @@ error[E0599]: `*const u8` doesn't implement `std::fmt::Display` --> $DIR/suggest-convert-ptr-to-ref.rs:5:22 | LL | println!("{}", z.to_string()); - | ^^^^^^^^^ `*const u8` cannot be formatted with the default formatter + | ^^^^^^^^^ method cannot be called on `*const u8` due to unsatisfied trait bounds | note: the method `to_string` exists on the type `&u8` --> $SRC_DIR/alloc/src/string.rs:LL:COL @@ -11,13 +11,12 @@ note: the method `to_string` exists on the type `&u8` = note: the following trait bounds were not satisfied: `*const u8: std::fmt::Display` which is required by `*const u8: ToString` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead error[E0599]: `*mut u8` doesn't implement `std::fmt::Display` --> $DIR/suggest-convert-ptr-to-ref.rs:8:22 | LL | println!("{}", t.to_string()); - | ^^^^^^^^^ `*mut u8` cannot be formatted with the default formatter + | ^^^^^^^^^ method cannot be called on `*mut u8` due to unsatisfied trait bounds | note: the method `to_string` exists on the type `&&mut u8` --> $SRC_DIR/alloc/src/string.rs:LL:COL @@ -26,7 +25,6 @@ note: the method `to_string` exists on the type `&&mut u8` = note: the following trait bounds were not satisfied: `*mut u8: std::fmt::Display` which is required by `*mut u8: ToString` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead error[E0599]: no method named `make_ascii_lowercase` found for raw pointer `*mut u8` in the current scope --> $DIR/suggest-convert-ptr-to-ref.rs:9:7 diff --git a/tests/crashes/131451.rs b/tests/ui/mir/unreachable-loop-jump-threading.rs similarity index 74% rename from tests/crashes/131451.rs rename to tests/ui/mir/unreachable-loop-jump-threading.rs index cd5b44bad8a5..8403906bb5c0 100644 --- a/tests/crashes/131451.rs +++ b/tests/ui/mir/unreachable-loop-jump-threading.rs @@ -1,9 +1,10 @@ -//@ known-bug: #131451 +//@ build-pass //@ needs-rustc-debug-assertions //@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+JumpThreading --crate-type=lib pub fn fun(terminate: bool) { while true {} + //~^ WARN denote infinite loops with `loop { ... }` while !terminate {} } diff --git a/tests/ui/mir/unreachable-loop-jump-threading.stderr b/tests/ui/mir/unreachable-loop-jump-threading.stderr new file mode 100644 index 000000000000..21b174c80218 --- /dev/null +++ b/tests/ui/mir/unreachable-loop-jump-threading.stderr @@ -0,0 +1,10 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/unreachable-loop-jump-threading.rs:6:5 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr index be3a3e2abf14..23bc9dc0f844 100644 --- a/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -2,9 +2,8 @@ error[E0277]: `Foo` doesn't implement `Debug` --> $DIR/method-help-unsatisfied-bound.rs:5:7 | LL | a.unwrap(); - | ^^^^^^ `Foo` cannot be formatted using `{:?}` + | ^^^^^^ the trait `Debug` is not implemented for `Foo` | - = help: the trait `Debug` is not implemented for `Foo` = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo` note: required by a bound in `Result::::unwrap` --> $SRC_DIR/core/src/result.rs:LL:COL diff --git a/tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs b/tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs index f589e88f68e4..0632b822c55c 100644 --- a/tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs +++ b/tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs @@ -2,17 +2,17 @@ #![crate_type = "lib"] pub fn foo(arg: Option<&Vec>) -> Option<&[i32]> { - arg //~ ERROR 5:5: 5:8: mismatched types [E0308] + arg //~ ERROR mismatched types [E0308] } pub fn bar(arg: Option<&Vec>) -> &[i32] { - arg.unwrap_or(&[]) //~ ERROR 9:19: 9:22: mismatched types [E0308] + arg.unwrap_or(&[]) //~ ERROR mismatched types [E0308] } pub fn barzz<'a>(arg: Option<&'a Vec>, v: &'a [i32]) -> &'a [i32] { - arg.unwrap_or(v) //~ ERROR 13:19: 13:20: mismatched types [E0308] + arg.unwrap_or(v) //~ ERROR mismatched types [E0308] } pub fn convert_result(arg: Result<&Vec, ()>) -> &[i32] { - arg.unwrap_or(&[]) //~ ERROR 17:19: 17:22: mismatched types [E0308] + arg.unwrap_or(&[]) //~ ERROR mismatched types [E0308] } diff --git a/tests/ui/modules/issue-107649.stderr b/tests/ui/modules/issue-107649.stderr index 0d203c1aacba..802ac669a10e 100644 --- a/tests/ui/modules/issue-107649.stderr +++ b/tests/ui/modules/issue-107649.stderr @@ -2,11 +2,10 @@ error[E0277]: `Dummy` doesn't implement `Debug` --> $DIR/issue-107649.rs:105:5 | 105 | dbg!(lib::Dummy); - | ^^^^^^^^^^^^^^^^ `Dummy` cannot be formatted using `{:?}` + | ^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `Dummy` | - = help: the trait `Debug` is not implemented for `Dummy` = note: add `#[derive(Debug)]` to `Dummy` or manually `impl Debug for Dummy` - = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Dummy` with `#[derive(Debug)]` --> $DIR/auxiliary/dummy_lib.rs:2:1 | diff --git a/tests/ui/never_type/never-type-fallback-option.rs b/tests/ui/never_type/never-type-fallback-option.rs new file mode 100644 index 000000000000..9c8103aa0a4c --- /dev/null +++ b/tests/ui/never_type/never-type-fallback-option.rs @@ -0,0 +1,22 @@ +//@ run-pass + +#![allow(warnings)] + +//! Tests type inference fallback to `!` (never type) in `Option` context. +//! +//! Regression test for issues: +//! - https://github.com/rust-lang/rust/issues/39808 +//! - https://github.com/rust-lang/rust/issues/39984 +//! +//! Here the type of `c` is `Option`, where `?T` is unconstrained. +//! Because there is data-flow from the `{ return; }` block, which +//! diverges and hence has type `!`, into `c`, we will default `?T` to +//! `!`, and hence this code compiles rather than failing and requiring +//! a type annotation. + +fn main() { + let c = Some({ + return; + }); + c.unwrap(); +} diff --git a/tests/ui/no_std/simple-runs.rs b/tests/ui/no_std/simple-runs.rs index 8931ac7ed11b..af44dfec311e 100644 --- a/tests/ui/no_std/simple-runs.rs +++ b/tests/ui/no_std/simple-runs.rs @@ -4,6 +4,7 @@ //@ compile-flags: -Cpanic=abort //@ ignore-wasm different `main` convention +#![feature(lang_items)] #![no_std] #![no_main] @@ -35,6 +36,17 @@ fn panic_handler(_info: &PanicInfo<'_>) -> ! { loop {} } +#[lang = "eh_personality"] +extern "C" fn rust_eh_personality( + _version: i32, + _actions: i32, + _exception_class: u64, + _exception_object: *mut (), + _context: *mut (), +) -> i32 { + loop {} +} + #[no_mangle] extern "C" fn main(_argc: c_int, _argv: *const *const c_char) -> c_int { 0 diff --git a/tests/ui/on-unimplemented/no-debug.stderr b/tests/ui/on-unimplemented/no-debug.stderr index 97d67dbd82e7..5b0b060d40ef 100644 --- a/tests/ui/on-unimplemented/no-debug.stderr +++ b/tests/ui/on-unimplemented/no-debug.stderr @@ -2,7 +2,9 @@ error[E0277]: `Foo` doesn't implement `Debug` --> $DIR/no-debug.rs:10:27 | LL | println!("{:?} {:?}", Foo, Bar); - | ^^^ `Foo` cannot be formatted using `{:?}` + | ---- ^^^ `Foo` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter | = help: the trait `Debug` is not implemented for `Foo` = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo` @@ -17,7 +19,9 @@ error[E0277]: `Bar` doesn't implement `Debug` --> $DIR/no-debug.rs:10:32 | LL | println!("{:?} {:?}", Foo, Bar); - | ^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ---- ^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter | = help: the trait `Debug` is not implemented for `Bar` = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -26,7 +30,9 @@ error[E0277]: `Foo` doesn't implement `std::fmt::Display` --> $DIR/no-debug.rs:11:23 | LL | println!("{} {}", Foo, Bar); - | ^^^ `Foo` cannot be formatted with the default formatter + | -- ^^^ `Foo` cannot be formatted with the default formatter + | | + | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `Foo` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead @@ -36,7 +42,9 @@ error[E0277]: `Bar` doesn't implement `std::fmt::Display` --> $DIR/no-debug.rs:11:28 | LL | println!("{} {}", Foo, Bar); - | ^^^ `Bar` cannot be formatted with the default formatter + | -- ^^^ `Bar` cannot be formatted with the default formatter + | | + | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `Bar` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead diff --git a/tests/ui/panic-runtime/incompatible-type.rs b/tests/ui/panic-runtime/incompatible-type.rs index 4cbcfec11c96..f82c23d68c2c 100644 --- a/tests/ui/panic-runtime/incompatible-type.rs +++ b/tests/ui/panic-runtime/incompatible-type.rs @@ -21,4 +21,12 @@ pub fn test(_: DropMe) { } #[rustc_std_internal_symbol] -pub unsafe extern "C" fn rust_eh_personality() {} +pub unsafe extern "C" fn rust_eh_personality( + _version: i32, + _actions: i32, + _exception_class: u64, + _exception_object: *mut (), + _context: *mut (), +) -> i32 { + loop {} +} diff --git a/tests/ui/panics/location-detail-unwrap-multiline.rs b/tests/ui/panics/location-detail-unwrap-multiline.rs index 56e1760d851b..e49e11a60610 100644 --- a/tests/ui/panics/location-detail-unwrap-multiline.rs +++ b/tests/ui/panics/location-detail-unwrap-multiline.rs @@ -1,7 +1,7 @@ //@ run-fail //@ compile-flags: -Cstrip=none -Cdebuginfo=line-tables-only -Copt-level=0 //@ exec-env:RUST_BACKTRACE=1 -//@ regex-error-pattern: location-detail-unwrap-multiline\.rs:11(:10)?\n +//@ regex-error-pattern: location-detail-unwrap-multiline\.rs:11(:10)?:\n //@ needs-unwind //@ ignore-android FIXME #17520 diff --git a/tests/ui/parser/bad-lit-suffixes.rs b/tests/ui/parser/bad-lit-suffixes.rs index f29dc53d322b..4e8edf4d46ea 100644 --- a/tests/ui/parser/bad-lit-suffixes.rs +++ b/tests/ui/parser/bad-lit-suffixes.rs @@ -33,7 +33,6 @@ fn f() {} #[must_use = "string"suffix] //~^ ERROR suffixes on string literals are invalid -//~| ERROR malformed `must_use` attribute input fn g() {} #[link(name = "string"suffix)] diff --git a/tests/ui/parser/bad-lit-suffixes.stderr b/tests/ui/parser/bad-lit-suffixes.stderr index 86ef35bf7833..416143e496af 100644 --- a/tests/ui/parser/bad-lit-suffixes.stderr +++ b/tests/ui/parser/bad-lit-suffixes.stderr @@ -22,29 +22,14 @@ error: suffixes on string literals are invalid LL | #[must_use = "string"suffix] | ^^^^^^^^^^^^^^ invalid suffix `suffix` -error: malformed `must_use` attribute input - --> $DIR/bad-lit-suffixes.rs:34:1 - | -LL | #[must_use = "string"suffix] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: the following are the possible correct uses - | -LL - #[must_use = "string"suffix] -LL + #[must_use = "reason"] - | -LL - #[must_use = "string"suffix] -LL + #[must_use] - | - error: suffixes on string literals are invalid - --> $DIR/bad-lit-suffixes.rs:39:15 + --> $DIR/bad-lit-suffixes.rs:38:15 | LL | #[link(name = "string"suffix)] | ^^^^^^^^^^^^^^ invalid suffix `suffix` error: invalid suffix `suffix` for number literal - --> $DIR/bad-lit-suffixes.rs:43:41 + --> $DIR/bad-lit-suffixes.rs:42:41 | LL | #[rustc_layout_scalar_valid_range_start(0suffix)] | ^^^^^^^ invalid suffix `suffix` @@ -165,5 +150,5 @@ LL | 1.0e10suffix; | = help: valid suffixes are `f32` and `f64` -error: aborting due to 21 previous errors; 2 warnings emitted +error: aborting due to 20 previous errors; 2 warnings emitted diff --git a/tests/ui/parser/issues/issue-105366.fixed b/tests/ui/parser/issues/issue-105366.fixed index 7157b647524d..95419dc07f2c 100644 --- a/tests/ui/parser/issues/issue-105366.fixed +++ b/tests/ui/parser/issues/issue-105366.fixed @@ -1,5 +1,6 @@ //@ run-rustfix +#[allow(dead_code)] struct Foo; impl From for Foo { diff --git a/tests/ui/parser/issues/issue-105366.rs b/tests/ui/parser/issues/issue-105366.rs index dc3cb8b343d3..3278b7379912 100644 --- a/tests/ui/parser/issues/issue-105366.rs +++ b/tests/ui/parser/issues/issue-105366.rs @@ -1,5 +1,6 @@ //@ run-rustfix +#[allow(dead_code)] struct Foo; fn From for Foo { diff --git a/tests/ui/parser/issues/issue-105366.stderr b/tests/ui/parser/issues/issue-105366.stderr index d8c79a0e0eaf..225e436b4aa8 100644 --- a/tests/ui/parser/issues/issue-105366.stderr +++ b/tests/ui/parser/issues/issue-105366.stderr @@ -1,5 +1,5 @@ error: you might have meant to write `impl` instead of `fn` - --> $DIR/issue-105366.rs:5:1 + --> $DIR/issue-105366.rs:6:1 | LL | fn From for Foo { | ^^ diff --git a/tests/ui/parser/macro/issue-33569.rs b/tests/ui/parser/macro/issue-33569.rs index e0a5352ab06d..7288fa858dbe 100644 --- a/tests/ui/parser/macro/issue-33569.rs +++ b/tests/ui/parser/macro/issue-33569.rs @@ -1,11 +1,10 @@ macro_rules! foo { { $+ } => { //~ ERROR expected identifier, found `+` //~^ ERROR missing fragment specifier - //~| ERROR missing fragment specifier $(x)(y) //~ ERROR expected one of: `*`, `+`, or `?` } } -foo!(); +foo!(); //~ ERROR unexpected end fn main() {} diff --git a/tests/ui/parser/macro/issue-33569.stderr b/tests/ui/parser/macro/issue-33569.stderr index 0d53c04c1c9f..dd8e38f0d6e9 100644 --- a/tests/ui/parser/macro/issue-33569.stderr +++ b/tests/ui/parser/macro/issue-33569.stderr @@ -4,12 +4,6 @@ error: expected identifier, found `+` LL | { $+ } => { | ^ -error: expected one of: `*`, `+`, or `?` - --> $DIR/issue-33569.rs:5:13 - | -LL | $(x)(y) - | ^^^ - error: missing fragment specifier --> $DIR/issue-33569.rs:2:8 | @@ -23,7 +17,22 @@ help: try adding a specifier here LL | { $+:spec } => { | +++++ -error: missing fragment specifier +error: expected one of: `*`, `+`, or `?` + --> $DIR/issue-33569.rs:4:13 + | +LL | $(x)(y) + | ^^^ + +error: unexpected end of macro invocation + --> $DIR/issue-33569.rs:8:1 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(); + | ^^^^^^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$:tt` --> $DIR/issue-33569.rs:2:8 | LL | { $+ } => { diff --git a/tests/ui/parser/recover/recover-field-semi.rs b/tests/ui/parser/recover/recover-field-semi.rs index b703578860ec..b6f235f8ad1c 100644 --- a/tests/ui/parser/recover/recover-field-semi.rs +++ b/tests/ui/parser/recover/recover-field-semi.rs @@ -3,7 +3,7 @@ struct Foo { //~^ ERROR struct fields are separated by `,` } -union Bar { //~ ERROR +union Bar { foo: i32; //~^ ERROR union fields are separated by `,` } @@ -13,4 +13,6 @@ enum Baz { //~^ ERROR struct fields are separated by `,` } -fn main() {} +fn main() { + let _ = Foo { foo: "" }; //~ ERROR mismatched types +} diff --git a/tests/ui/parser/recover/recover-field-semi.stderr b/tests/ui/parser/recover/recover-field-semi.stderr index 3cf4847488c0..9b1a34e134b6 100644 --- a/tests/ui/parser/recover/recover-field-semi.stderr +++ b/tests/ui/parser/recover/recover-field-semi.stderr @@ -22,14 +22,12 @@ LL | Qux { foo: i32; } | | | while parsing this struct -error: unions cannot have zero fields - --> $DIR/recover-field-semi.rs:6:1 +error[E0308]: mismatched types + --> $DIR/recover-field-semi.rs:17:24 | -LL | / union Bar { -LL | | foo: i32; -LL | | -LL | | } - | |_^ +LL | let _ = Foo { foo: "" }; + | ^^ expected `i32`, found `&str` error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr new file mode 100644 index 000000000000..cc438461a5d1 --- /dev/null +++ b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr @@ -0,0 +1,238 @@ +error[E0382]: use of moved value: `foo` + --> $DIR/borrow-unpin.rs:39:14 + | +LL | let foo = Foo::default(); + | --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait +LL | foo_pin_mut(&pin mut foo); + | --- value moved here +LL | foo_move(foo); + | ^^^ value used here after move + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:16:1 + | +LL | struct Foo(PhantomPinned); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | foo_pin_mut(&pin mut foo); + | --- you could clone this value + +error[E0382]: use of moved value: `foo` + --> $DIR/borrow-unpin.rs:43:14 + | +LL | let foo = Foo::default(); + | --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait +LL | let x = &pin mut foo; + | --- value moved here +LL | foo_move(foo); + | ^^^ value used here after move + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:16:1 + | +LL | struct Foo(PhantomPinned); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = &pin mut foo; + | --- you could clone this value + +error[E0382]: use of moved value: `foo` + --> $DIR/borrow-unpin.rs:52:14 + | +LL | let mut foo = Foo::default(); + | ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait +LL | foo_pin_mut(&pin mut foo); // ok + | --- value moved here +LL | foo_move(foo); + | ^^^ value used here after move + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:16:1 + | +LL | struct Foo(PhantomPinned); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | foo_pin_mut(&pin mut foo); // ok + | --- you could clone this value + +error[E0382]: use of moved value: `foo` + --> $DIR/borrow-unpin.rs:56:14 + | +LL | let mut foo = Foo::default(); + | ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait +LL | let x = &pin mut foo; // ok + | --- value moved here +LL | foo_move(foo); + | ^^^ value used here after move + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:16:1 + | +LL | struct Foo(PhantomPinned); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = &pin mut foo; // ok + | --- you could clone this value + +error[E0505]: cannot move out of `foo` because it is borrowed + --> $DIR/borrow-unpin.rs:68:14 + | +LL | let foo = Foo::default(); + | --- binding `foo` declared here +LL | let x = &pin const foo; // ok + | -------------- borrow of `foo` occurs here +LL | foo_move(foo); + | ^^^ move out of `foo` occurs here +LL | +LL | foo_pin_ref(x); + | - borrow later used here + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:16:1 + | +LL | struct Foo(PhantomPinned); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = &pin const foo; // ok + | --- you could clone this value + +error[E0382]: borrow of moved value: `foo` + --> $DIR/borrow-unpin.rs:76:13 + | +LL | let mut foo = Foo::default(); + | ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait +LL | foo_pin_mut(&pin mut foo); // ok + | --- value moved here +LL | foo_ref(&foo); + | ^^^^ value borrowed here after move + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:16:1 + | +LL | struct Foo(PhantomPinned); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | foo_pin_mut(&pin mut foo); // ok + | --- you could clone this value + +error[E0382]: borrow of moved value: `foo` + --> $DIR/borrow-unpin.rs:80:13 + | +LL | let mut foo = Foo::default(); + | ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait +LL | let x = &pin mut foo; // ok + | --- value moved here +LL | foo_ref(&foo); + | ^^^^ value borrowed here after move + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:16:1 + | +LL | struct Foo(PhantomPinned); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = &pin mut foo; // ok + | --- you could clone this value + +error[E0382]: use of moved value: `foo` + --> $DIR/borrow-unpin.rs:99:26 + | +LL | let mut foo = Foo::default(); + | ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait +LL | foo_pin_mut(&pin mut foo); // ok + | --- value moved here +LL | foo_pin_mut(&pin mut foo); + | ^^^ value used here after move + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:16:1 + | +LL | struct Foo(PhantomPinned); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | foo_pin_mut(&pin mut foo); // ok + | --- you could clone this value + +error[E0382]: use of moved value: `foo` + --> $DIR/borrow-unpin.rs:103:26 + | +LL | let mut foo = Foo::default(); + | ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait +LL | let x = &pin mut foo; // ok + | --- value moved here +LL | foo_pin_mut(&pin mut foo); + | ^^^ value used here after move + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:16:1 + | +LL | struct Foo(PhantomPinned); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = &pin mut foo; // ok + | --- you could clone this value + +error[E0505]: cannot move out of `foo` because it is borrowed + --> $DIR/borrow-unpin.rs:115:26 + | +LL | let mut foo = Foo::default(); + | ------- binding `foo` declared here +LL | let x = &pin const foo; // ok + | -------------- borrow of `foo` occurs here +LL | foo_pin_mut(&pin mut foo); + | ^^^ move out of `foo` occurs here +LL | +LL | foo_pin_ref(x); + | - borrow later used here + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:16:1 + | +LL | struct Foo(PhantomPinned); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = &pin const foo; // ok + | --- you could clone this value + +error[E0382]: borrow of moved value: `foo` + --> $DIR/borrow-unpin.rs:123:17 + | +LL | let mut foo = Foo::default(); + | ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait +LL | foo_pin_mut(&pin mut foo); // ok + | --- value moved here +LL | foo_pin_ref(&pin const foo); + | ^^^^^^^^^^^^^^ value borrowed here after move + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:16:1 + | +LL | struct Foo(PhantomPinned); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | foo_pin_mut(&pin mut foo); // ok + | --- you could clone this value + +error[E0382]: borrow of moved value: `foo` + --> $DIR/borrow-unpin.rs:127:17 + | +LL | let mut foo = Foo::default(); + | ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait +LL | let x = &pin mut foo; // ok + | --- value moved here +LL | foo_pin_ref(&pin const foo); + | ^^^^^^^^^^^^^^ value borrowed here after move + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:16:1 + | +LL | struct Foo(PhantomPinned); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = &pin mut foo; // ok + | --- you could clone this value + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0382, E0505. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pin-ergonomics/borrow-unpin.rs b/tests/ui/pin-ergonomics/borrow-unpin.rs new file mode 100644 index 000000000000..61e69bab12bc --- /dev/null +++ b/tests/ui/pin-ergonomics/borrow-unpin.rs @@ -0,0 +1,143 @@ +//@ revisions: unpin pinned +#![feature(pin_ergonomics)] +#![allow(dead_code, incomplete_features)] + +// For now, in order to ensure soundness, we move the place in `&pin mut place` +// if `place` is not `Unpin`. +// In the next step, we borrow the place instead of moving it, after that we +// have to makes sure `&pin mut place` and `&pin const place` cannot violate +// the mut-xor-share rules. + +use std::pin::Pin; +use std::marker::PhantomPinned; + +#[cfg(pinned)] +#[derive(Default)] +struct Foo(PhantomPinned); + +#[cfg(unpin)] +#[derive(Default)] +struct Foo; + +fn foo_mut(_: &mut Foo) { +} + +fn foo_ref(_: &Foo) { +} + +fn foo_pin_mut(_: Pin<&mut Foo>) { +} + +fn foo_pin_ref(_: Pin<&Foo>) { +} + +fn foo_move(_: Foo) {} + +fn immutable_pin_mut_then_move() { + let foo = Foo::default(); + foo_pin_mut(&pin mut foo); //[unpin]~ ERROR cannot borrow `foo` as mutable, as it is not declared as mutable + foo_move(foo); //[pinned]~ ERROR use of moved value: `foo` + + let foo = Foo::default(); + let x = &pin mut foo; //[unpin]~ ERROR cannot borrow `foo` as mutable, as it is not declared as mutable + foo_move(foo); //[pinned]~ ERROR use of moved value: `foo` + //[unpin]~^ ERROR cannot move out of `foo` because it is borrowed + foo_pin_mut(x); // +} + + +fn pin_mut_then_move() { + let mut foo = Foo::default(); + foo_pin_mut(&pin mut foo); // ok + foo_move(foo); //[pinned]~ ERROR use of moved value: `foo` + + let mut foo = Foo::default(); + let x = &pin mut foo; // ok + foo_move(foo); //[pinned]~ ERROR use of moved value: `foo` + //[unpin]~^ ERROR cannot move out of `foo` because it is borrowed + foo_pin_mut(x); // +} + +fn pin_ref_then_move() { + let foo = Foo::default(); + foo_pin_ref(&pin const foo); // ok + foo_move(foo); // ok + + let foo = Foo::default(); + let x = &pin const foo; // ok + foo_move(foo); //[pinned]~ ERROR cannot move out of `foo` because it is borrowed + //[unpin]~^ ERROR cannot move out of `foo` because it is borrowed + foo_pin_ref(x); +} + +fn pin_mut_then_ref() { + let mut foo = Foo::default(); + foo_pin_mut(&pin mut foo); // ok + foo_ref(&foo); //[pinned]~ ERROR borrow of moved value: `foo` + + let mut foo = Foo::default(); + let x = &pin mut foo; // ok + foo_ref(&foo); //[pinned]~ ERROR borrow of moved value: `foo` + //[unpin]~^ ERROR cannot borrow `foo` as immutable because it is also borrowed as mutable + foo_pin_mut(x); +} + +fn pin_ref_then_ref() { + let mut foo = Foo::default(); + foo_pin_ref(&pin const foo); // ok + foo_ref(&foo); // ok + + let mut foo = Foo::default(); + let x = &pin const foo; // ok + foo_ref(&foo); // ok + foo_pin_ref(x); +} + +fn pin_mut_then_pin_mut() { + let mut foo = Foo::default(); + foo_pin_mut(&pin mut foo); // ok + foo_pin_mut(&pin mut foo); //[pinned]~ ERROR use of moved value: `foo` + + let mut foo = Foo::default(); + let x = &pin mut foo; // ok + foo_pin_mut(&pin mut foo); //[pinned]~ ERROR use of moved value: `foo` + //[unpin]~^ ERROR cannot borrow `foo` as mutable more than once at a time + foo_pin_mut(x); +} + +fn pin_ref_then_pin_mut() { + let mut foo = Foo::default(); + foo_pin_ref(&pin const foo); // ok + foo_pin_mut(&pin mut foo); // ok + + let mut foo = Foo::default(); + let x = &pin const foo; // ok + foo_pin_mut(&pin mut foo); //[pinned]~ ERROR cannot move out of `foo` because it is borrowed + //[unpin]~^ ERROR cannot borrow `foo` as mutable because it is also borrowed as immutable + foo_pin_ref(x); +} + +fn pin_mut_then_pin_ref() { + let mut foo = Foo::default(); + foo_pin_mut(&pin mut foo); // ok + foo_pin_ref(&pin const foo); //[pinned]~ ERROR borrow of moved value: `foo` + + let mut foo = Foo::default(); + let x = &pin mut foo; // ok + foo_pin_ref(&pin const foo); //[pinned]~ ERROR borrow of moved value: `foo` + //[unpin]~^ ERROR cannot borrow `foo` as immutable because it is also borrowed as mutable + foo_pin_mut(x); +} + +fn pin_ref_then_pin_ref() { + let mut foo = Foo::default(); + foo_pin_ref(&pin const foo); // ok + foo_pin_ref(&pin const foo); // ok + + let mut foo = Foo::default(); + let x = &pin const foo; // ok + foo_pin_ref(&pin const foo); // ok + foo_pin_ref(x); +} + +fn main() {} diff --git a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr new file mode 100644 index 000000000000..bf9921343ee7 --- /dev/null +++ b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr @@ -0,0 +1,136 @@ +error[E0596]: cannot borrow `foo` as mutable, as it is not declared as mutable + --> $DIR/borrow-unpin.rs:38:17 + | +LL | foo_pin_mut(&pin mut foo); + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut foo = Foo::default(); + | +++ + +error[E0596]: cannot borrow `foo` as mutable, as it is not declared as mutable + --> $DIR/borrow-unpin.rs:42:13 + | +LL | let x = &pin mut foo; + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut foo = Foo::default(); + | +++ + +error[E0505]: cannot move out of `foo` because it is borrowed + --> $DIR/borrow-unpin.rs:43:14 + | +LL | let foo = Foo::default(); + | --- binding `foo` declared here +LL | let x = &pin mut foo; + | ------------ borrow of `foo` occurs here +LL | foo_move(foo); + | ^^^ move out of `foo` occurs here +LL | +LL | foo_pin_mut(x); // + | - borrow later used here + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:20:1 + | +LL | struct Foo; + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = &pin mut foo; + | --- you could clone this value + +error[E0505]: cannot move out of `foo` because it is borrowed + --> $DIR/borrow-unpin.rs:56:14 + | +LL | let mut foo = Foo::default(); + | ------- binding `foo` declared here +LL | let x = &pin mut foo; // ok + | ------------ borrow of `foo` occurs here +LL | foo_move(foo); + | ^^^ move out of `foo` occurs here +LL | +LL | foo_pin_mut(x); // + | - borrow later used here + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:20:1 + | +LL | struct Foo; + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = &pin mut foo; // ok + | --- you could clone this value + +error[E0505]: cannot move out of `foo` because it is borrowed + --> $DIR/borrow-unpin.rs:68:14 + | +LL | let foo = Foo::default(); + | --- binding `foo` declared here +LL | let x = &pin const foo; // ok + | -------------- borrow of `foo` occurs here +LL | foo_move(foo); + | ^^^ move out of `foo` occurs here +LL | +LL | foo_pin_ref(x); + | - borrow later used here + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/borrow-unpin.rs:20:1 + | +LL | struct Foo; + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = &pin const foo; // ok + | --- you could clone this value + +error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable + --> $DIR/borrow-unpin.rs:80:13 + | +LL | let x = &pin mut foo; // ok + | ------------ mutable borrow occurs here +LL | foo_ref(&foo); + | ^^^^ immutable borrow occurs here +LL | +LL | foo_pin_mut(x); + | - mutable borrow later used here + +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/borrow-unpin.rs:103:17 + | +LL | let x = &pin mut foo; // ok + | ------------ first mutable borrow occurs here +LL | foo_pin_mut(&pin mut foo); + | ^^^^^^^^^^^^ second mutable borrow occurs here +LL | +LL | foo_pin_mut(x); + | - first borrow later used here + +error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable + --> $DIR/borrow-unpin.rs:115:17 + | +LL | let x = &pin const foo; // ok + | -------------- immutable borrow occurs here +LL | foo_pin_mut(&pin mut foo); + | ^^^^^^^^^^^^ mutable borrow occurs here +LL | +LL | foo_pin_ref(x); + | - immutable borrow later used here + +error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable + --> $DIR/borrow-unpin.rs:127:17 + | +LL | let x = &pin mut foo; // ok + | ------------ mutable borrow occurs here +LL | foo_pin_ref(&pin const foo); + | ^^^^^^^^^^^^^^ immutable borrow occurs here +LL | +LL | foo_pin_mut(x); + | - mutable borrow later used here + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0499, E0502, E0505, E0596. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/pin-ergonomics/borrow.rs b/tests/ui/pin-ergonomics/borrow.rs new file mode 100644 index 000000000000..f221165848ba --- /dev/null +++ b/tests/ui/pin-ergonomics/borrow.rs @@ -0,0 +1,38 @@ +//@ check-pass +#![feature(pin_ergonomics)] +#![allow(dead_code, incomplete_features)] + +// Makes sure we can handle `&pin mut place` and `&pin const place` as sugar for +// `std::pin::pin!(place)` and `Pin::new(&place)`. + +use std::pin::Pin; + +struct Foo; + +fn foo_pin_mut(_: Pin<&mut Foo>) { +} + +fn foo_pin_ref(_: Pin<&Foo>) { +} + +fn bar() { + let mut x: Pin<&mut _> = &pin mut Foo; + foo_pin_mut(x.as_mut()); + foo_pin_mut(x.as_mut()); + foo_pin_ref(x); + + let x: Pin<&_> = &pin const Foo; + + foo_pin_ref(x); + foo_pin_ref(x); +} + +fn baz(mut x: Foo, y: Foo) { + let _x = &pin mut x; + let _x = x; // ok because `Foo: Unpin` and thus `&pin mut x` doesn't move `x` + + let _y = &pin const y; + let _y = y; // ok because `&pin const y` dosn't move `y` +} + +fn main() {} diff --git a/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.rs b/tests/ui/pin-ergonomics/coerce-non-pointer-pin.rs similarity index 100% rename from tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.rs rename to tests/ui/pin-ergonomics/coerce-non-pointer-pin.rs diff --git a/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.stderr b/tests/ui/pin-ergonomics/coerce-non-pointer-pin.stderr similarity index 100% rename from tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.stderr rename to tests/ui/pin-ergonomics/coerce-non-pointer-pin.stderr diff --git a/tests/ui/async-await/pin-ergonomics/reborrow-arg.rs b/tests/ui/pin-ergonomics/reborrow-arg.rs similarity index 100% rename from tests/ui/async-await/pin-ergonomics/reborrow-arg.rs rename to tests/ui/pin-ergonomics/reborrow-arg.rs diff --git a/tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.rs b/tests/ui/pin-ergonomics/reborrow-const-as-mut.rs similarity index 100% rename from tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.rs rename to tests/ui/pin-ergonomics/reborrow-const-as-mut.rs diff --git a/tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.stderr b/tests/ui/pin-ergonomics/reborrow-const-as-mut.stderr similarity index 100% rename from tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.stderr rename to tests/ui/pin-ergonomics/reborrow-const-as-mut.stderr diff --git a/tests/ui/async-await/pin-ergonomics/reborrow-once.rs b/tests/ui/pin-ergonomics/reborrow-once.rs similarity index 100% rename from tests/ui/async-await/pin-ergonomics/reborrow-once.rs rename to tests/ui/pin-ergonomics/reborrow-once.rs diff --git a/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr b/tests/ui/pin-ergonomics/reborrow-once.stderr similarity index 100% rename from tests/ui/async-await/pin-ergonomics/reborrow-once.stderr rename to tests/ui/pin-ergonomics/reborrow-once.stderr diff --git a/tests/ui/async-await/pin-ergonomics/reborrow-self.rs b/tests/ui/pin-ergonomics/reborrow-self.rs similarity index 100% rename from tests/ui/async-await/pin-ergonomics/reborrow-self.rs rename to tests/ui/pin-ergonomics/reborrow-self.rs diff --git a/tests/ui/async-await/pin-ergonomics/reborrow-shorter.rs b/tests/ui/pin-ergonomics/reborrow-shorter.rs similarity index 100% rename from tests/ui/async-await/pin-ergonomics/reborrow-shorter.rs rename to tests/ui/pin-ergonomics/reborrow-shorter.rs diff --git a/tests/ui/async-await/pin-ergonomics/sugar-ambiguity.rs b/tests/ui/pin-ergonomics/sugar-ambiguity.rs similarity index 100% rename from tests/ui/async-await/pin-ergonomics/sugar-ambiguity.rs rename to tests/ui/pin-ergonomics/sugar-ambiguity.rs diff --git a/tests/ui/async-await/pin-ergonomics/sugar-no-const.rs b/tests/ui/pin-ergonomics/sugar-no-const.rs similarity index 100% rename from tests/ui/async-await/pin-ergonomics/sugar-no-const.rs rename to tests/ui/pin-ergonomics/sugar-no-const.rs diff --git a/tests/ui/async-await/pin-ergonomics/sugar-no-const.stderr b/tests/ui/pin-ergonomics/sugar-no-const.stderr similarity index 100% rename from tests/ui/async-await/pin-ergonomics/sugar-no-const.stderr rename to tests/ui/pin-ergonomics/sugar-no-const.stderr diff --git a/tests/ui/async-await/pin-ergonomics/sugar-self.rs b/tests/ui/pin-ergonomics/sugar-self.rs similarity index 100% rename from tests/ui/async-await/pin-ergonomics/sugar-self.rs rename to tests/ui/pin-ergonomics/sugar-self.rs diff --git a/tests/ui/async-await/pin-ergonomics/sugar.rs b/tests/ui/pin-ergonomics/sugar.rs similarity index 100% rename from tests/ui/async-await/pin-ergonomics/sugar.rs rename to tests/ui/pin-ergonomics/sugar.rs diff --git a/tests/ui/print-calling-conventions.stdout b/tests/ui/print-calling-conventions.stdout index 7b5ae4956606..b8b939e1c04e 100644 --- a/tests/ui/print-calling-conventions.stdout +++ b/tests/ui/print-calling-conventions.stdout @@ -1,6 +1,4 @@ C -C-cmse-nonsecure-call -C-cmse-nonsecure-entry C-unwind Rust aapcs @@ -9,6 +7,8 @@ avr-interrupt avr-non-blocking-interrupt cdecl cdecl-unwind +cmse-nonsecure-call +cmse-nonsecure-entry custom efiapi fastcall @@ -20,6 +20,7 @@ riscv-interrupt-m riscv-interrupt-s rust-call rust-cold +rust-invalid stdcall stdcall-unwind system diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr index 37669dd3f47c..8878ba143097 100644 --- a/tests/ui/range/range-1.stderr +++ b/tests/ui/range/range-1.stderr @@ -10,16 +10,6 @@ error[E0277]: the trait bound `bool: Step` is not satisfied LL | for i in false..true {} | ^^^^^^^^^^^ the trait `Step` is not implemented for `bool` | - = help: the following other types implement trait `Step`: - Char - Ipv4Addr - Ipv6Addr - char - i128 - i16 - i32 - i64 - and 8 others = note: required for `std::ops::Range` to implement `Iterator` = note: required for `std::ops::Range` to implement `IntoIterator` diff --git a/tests/ui/repr/attr-usage-repr.rs b/tests/ui/repr/attr-usage-repr.rs index cbf99f16e036..ca63ac564fc5 100644 --- a/tests/ui/repr/attr-usage-repr.rs +++ b/tests/ui/repr/attr-usage-repr.rs @@ -45,7 +45,7 @@ enum EInt { B, } -#[repr()] //~ ERROR attribute should be applied to a struct, enum, function, associated function, or union [E0517] +#[repr()] //~ ERROR attribute should be applied to a struct, enum, or union [E0517] type SirThisIsAType = i32; #[repr()] diff --git a/tests/ui/repr/attr-usage-repr.stderr b/tests/ui/repr/attr-usage-repr.stderr index a25e68c483f6..a62992c597a2 100644 --- a/tests/ui/repr/attr-usage-repr.stderr +++ b/tests/ui/repr/attr-usage-repr.stderr @@ -36,13 +36,13 @@ LL | | B, LL | | } | |_- not a struct -error[E0517]: attribute should be applied to a struct, enum, function, associated function, or union +error[E0517]: attribute should be applied to a struct, enum, or union --> $DIR/attr-usage-repr.rs:48:1 | LL | #[repr()] | ^^^^^^^^^ LL | type SirThisIsAType = i32; - | -------------------------- not a struct, enum, function, associated function, or union + | -------------------------- not a struct, enum, or union error: aborting due to 5 previous errors diff --git a/tests/ui/repr/malformed-repr-hints.stderr b/tests/ui/repr/malformed-repr-hints.stderr index 7a6e9ccc73eb..6fb927557619 100644 --- a/tests/ui/repr/malformed-repr-hints.stderr +++ b/tests/ui/repr/malformed-repr-hints.stderr @@ -1,15 +1,3 @@ -error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses - --> $DIR/malformed-repr-hints.rs:14:8 - | -LL | #[repr(align(2, 4))] - | ^^^^^^^^^^^ - -error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses - --> $DIR/malformed-repr-hints.rs:18:8 - | -LL | #[repr(align())] - | ^^^^^^^ - error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all --> $DIR/malformed-repr-hints.rs:6:8 | @@ -22,6 +10,18 @@ error[E0589]: invalid `repr(align)` attribute: `align` needs an argument LL | #[repr(align)] | ^^^^^ help: supply an argument here: `align(...)` +error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses + --> $DIR/malformed-repr-hints.rs:14:8 + | +LL | #[repr(align(2, 4))] + | ^^^^^^^^^^^ + +error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses + --> $DIR/malformed-repr-hints.rs:18:8 + | +LL | #[repr(align())] + | ^^^^^^^ + error[E0552]: invalid representation hint: `Rust` does not take a parenthesized argument list --> $DIR/malformed-repr-hints.rs:23:8 | diff --git a/tests/ui/repr/repr.stderr b/tests/ui/repr/repr.stderr index f3b11398eaa4..9e5813322783 100644 --- a/tests/ui/repr/repr.stderr +++ b/tests/ui/repr/repr.stderr @@ -5,7 +5,7 @@ LL | #[repr] | ^^^^^^^ | | | expected this to be a list - | help: must be of the form: `#[repr(C)]` + | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | | transparent)]` error[E0539]: malformed `repr` attribute input --> $DIR/repr.rs:4:1 @@ -14,7 +14,7 @@ LL | #[repr = "B"] | ^^^^^^^^^^^^^ | | | expected this to be a list - | help: must be of the form: `#[repr(C)]` + | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | | transparent)]` error[E0539]: malformed `repr` attribute input --> $DIR/repr.rs:7:1 @@ -23,7 +23,7 @@ LL | #[repr = "C"] | ^^^^^^^^^^^^^ | | | expected this to be a list - | help: must be of the form: `#[repr(C)]` + | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | | transparent)]` error: aborting due to 3 previous errors diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.stderr index e22d812c8b03..6088945b829c 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.stderr @@ -1,8 +1,12 @@ -error: malformed `track_caller` attribute input +error[E0565]: malformed `track_caller` attribute input --> $DIR/error-odd-syntax.rs:1:1 | LL | #[track_caller(1)] - | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]` + | ^^^^^^^^^^^^^^---^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[track_caller]` error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr index d3cafbc63508..303608061388 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr @@ -1,17 +1,17 @@ error[E0736]: attribute incompatible with `#[unsafe(naked)]` - --> $DIR/error-with-naked.rs:5:1 + --> $DIR/error-with-naked.rs:5:3 | LL | #[track_caller] - | ^^^^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[unsafe(naked)]` + | ^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[unsafe(naked)]` LL | LL | #[unsafe(naked)] | ---------------- function marked with `#[unsafe(naked)]` here error[E0736]: attribute incompatible with `#[unsafe(naked)]` - --> $DIR/error-with-naked.rs:17:5 + --> $DIR/error-with-naked.rs:17:7 | LL | #[track_caller] - | ^^^^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[unsafe(naked)]` + | ^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[unsafe(naked)]` LL | LL | #[unsafe(naked)] | ---------------- function marked with `#[unsafe(naked)]` here diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-ref-impl.rs b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-ref-impl.rs new file mode 100644 index 000000000000..c6e38c0758d7 --- /dev/null +++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-ref-impl.rs @@ -0,0 +1,17 @@ +/// Check that only `&X: Debug` is required, not `X: Debug` +//@check-pass + +use std::fmt::Debug; +use std::fmt::Formatter; + +struct X; + +impl Debug for &X { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + f.write_str("X") + } +} + +fn main() { + dbg!(X); +} diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs index f2fb62d76f3d..fe71f106fdf9 100644 --- a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs +++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs @@ -1,4 +1,7 @@ // Test ensuring that `dbg!(expr)` requires the passed type to implement `Debug`. +// +// `dbg!` shouldn't tell the user about format literal syntax; the user didn't write one. +//@ forbid-output: cannot be formatted using struct NotDebug; diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr index 7ec018a95cc7..4e0ae9184150 100644 --- a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr +++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr @@ -1,12 +1,11 @@ error[E0277]: `NotDebug` doesn't implement `Debug` - --> $DIR/dbg-macro-requires-debug.rs:6:23 + --> $DIR/dbg-macro-requires-debug.rs:9:23 | LL | let _: NotDebug = dbg!(NotDebug); - | ^^^^^^^^^^^^^^ `NotDebug` cannot be formatted using `{:?}` + | ^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `NotDebug` | - = help: the trait `Debug` is not implemented for `NotDebug` = note: add `#[derive(Debug)]` to `NotDebug` or manually `impl Debug for NotDebug` - = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `NotDebug` with `#[derive(Debug)]` | LL + #[derive(Debug)] diff --git a/tests/ui/rustdoc/renamed-features-rustdoc_internals.rs b/tests/ui/rustdoc/renamed-features-rustdoc_internals.rs index 2257130280dc..739c624d0c6f 100644 --- a/tests/ui/rustdoc/renamed-features-rustdoc_internals.rs +++ b/tests/ui/rustdoc/renamed-features-rustdoc_internals.rs @@ -1,5 +1,3 @@ -//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION" - #![feature(doc_keyword)] //~ ERROR #![feature(doc_primitive)] //~ ERROR #![crate_type = "lib"] diff --git a/tests/ui/rustdoc/renamed-features-rustdoc_internals.stderr b/tests/ui/rustdoc/renamed-features-rustdoc_internals.stderr index 9c664da8ee6c..0608a8b58a21 100644 --- a/tests/ui/rustdoc/renamed-features-rustdoc_internals.stderr +++ b/tests/ui/rustdoc/renamed-features-rustdoc_internals.stderr @@ -1,19 +1,19 @@ error[E0557]: feature has been removed - --> $DIR/renamed-features-rustdoc_internals.rs:3:12 + --> $DIR/renamed-features-rustdoc_internals.rs:1:12 | LL | #![feature(doc_keyword)] | ^^^^^^^^^^^ feature has been removed | - = note: removed in 1.58.0 (you are using $RUSTC_VERSION); see for more information + = note: removed in 1.58.0; see for more information = note: merged into `#![feature(rustdoc_internals)]` error[E0557]: feature has been removed - --> $DIR/renamed-features-rustdoc_internals.rs:4:12 + --> $DIR/renamed-features-rustdoc_internals.rs:2:12 | LL | #![feature(doc_primitive)] | ^^^^^^^^^^^^^ feature has been removed | - = note: removed in 1.58.0 (you are using $RUSTC_VERSION); see for more information + = note: removed in 1.58.0; see for more information = note: merged into `#![feature(rustdoc_internals)]` error: aborting due to 2 previous errors diff --git a/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs b/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs index 7ef6bd2f0acc..23ffabad62fe 100644 --- a/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs +++ b/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs @@ -7,5 +7,5 @@ #![no_core] #![no_main] -#[cfi_encoding] //~ERROR 10:1: 10:16: malformed `cfi_encoding` attribute input +#[cfi_encoding] //~ ERROR malformed `cfi_encoding` attribute input pub struct Type1(i32); diff --git a/tests/ui/sized/unsized-binding.rs b/tests/ui/sized/unsized-binding.rs index 3b99b0f6e965..ce6c15273764 100644 --- a/tests/ui/sized/unsized-binding.rs +++ b/tests/ui/sized/unsized-binding.rs @@ -1,5 +1,5 @@ fn main() { let x = *""; //~ ERROR E0277 - println!("{}", x); - println!("{}", x); + drop(x); + drop(x); } diff --git a/tests/ui/span/issue-71363.stderr b/tests/ui/span/issue-71363.stderr index 90b623e89cff..31069914daac 100644 --- a/tests/ui/span/issue-71363.stderr +++ b/tests/ui/span/issue-71363.stderr @@ -2,10 +2,8 @@ error[E0277]: `MyError` doesn't implement `std::fmt::Display` --> $DIR/issue-71363.rs:4:28 | 4 | impl std::error::Error for MyError {} - | ^^^^^^^ `MyError` cannot be formatted with the default formatter + | ^^^^^^^ the trait `std::fmt::Display` is not implemented for `MyError` | - = help: the trait `std::fmt::Display` is not implemented for `MyError` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `std::error::Error` --> $SRC_DIR/core/src/error.rs:LL:COL @@ -13,9 +11,8 @@ error[E0277]: `MyError` doesn't implement `Debug` --> $DIR/issue-71363.rs:4:28 | 4 | impl std::error::Error for MyError {} - | ^^^^^^^ `MyError` cannot be formatted using `{:?}` + | ^^^^^^^ the trait `Debug` is not implemented for `MyError` | - = help: the trait `Debug` is not implemented for `MyError` = note: add `#[derive(Debug)]` to `MyError` or manually `impl Debug for MyError` note: required by a bound in `std::error::Error` --> $SRC_DIR/core/src/error.rs:LL:COL diff --git a/tests/ui/statics/read_before_init.rs b/tests/ui/statics/read_before_init.rs new file mode 100644 index 000000000000..d779ef6dffab --- /dev/null +++ b/tests/ui/statics/read_before_init.rs @@ -0,0 +1,22 @@ +//! This test checks the one code path that does not go through +//! the regular CTFE memory access (as an optimization). We forgot +//! to duplicate the static item self-initialization check, allowing +//! reading from the uninitialized static memory before it was +//! initialized at the end of the static initializer. +//! +//! https://github.com/rust-lang/rust/issues/142532 + +use std::mem::MaybeUninit; + +pub static X: (i32, MaybeUninit) = (1, foo(&X.0)); +//~^ ERROR: encountered static that tried to initialize itself with itself + +const fn foo(x: &i32) -> MaybeUninit { + let mut temp = MaybeUninit::::uninit(); + unsafe { + std::ptr::copy(x, temp.as_mut_ptr(), 1); + } + temp +} + +fn main() {} diff --git a/tests/ui/statics/read_before_init.stderr b/tests/ui/statics/read_before_init.stderr new file mode 100644 index 000000000000..aeebcf7d9ce5 --- /dev/null +++ b/tests/ui/statics/read_before_init.stderr @@ -0,0 +1,17 @@ +error[E0080]: encountered static that tried to initialize itself with itself + --> $DIR/read_before_init.rs:11:45 + | +LL | pub static X: (i32, MaybeUninit) = (1, foo(&X.0)); + | ^^^^^^^^^ evaluation of `X` failed inside this call + | +note: inside `foo` + --> $DIR/read_before_init.rs:17:9 + | +LL | std::ptr::copy(x, temp.as_mut_ptr(), 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: inside `std::ptr::copy::` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 88f91bef30b1..b3b8784fa270 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -1,52 +1,7 @@ -ast-stats POST EXPANSION AST STATS +ast-stats ================================================================ +ast-stats POST EXPANSION AST STATS: input_stats ast-stats Name Accumulated Size Count Item Size ast-stats ---------------------------------------------------------------- -ast-stats Crate 40 (NN.N%) 1 40 -ast-stats GenericArgs 40 (NN.N%) 1 40 -ast-stats - AngleBracketed 40 (NN.N%) 1 -ast-stats ExprField 48 (NN.N%) 1 48 -ast-stats WherePredicate 72 (NN.N%) 1 72 -ast-stats - BoundPredicate 72 (NN.N%) 1 -ast-stats ForeignItem 80 (NN.N%) 1 80 -ast-stats - Fn 80 (NN.N%) 1 -ast-stats Arm 96 (NN.N%) 2 48 -ast-stats Local 96 (NN.N%) 1 96 -ast-stats FnDecl 120 (NN.N%) 5 24 -ast-stats InlineAsm 120 (NN.N%) 1 120 -ast-stats Attribute 128 (NN.N%) 4 32 -ast-stats - DocComment 32 (NN.N%) 1 -ast-stats - Normal 96 (NN.N%) 3 -ast-stats Param 160 (NN.N%) 4 40 -ast-stats Stmt 160 (NN.N%) 5 32 -ast-stats - Let 32 (NN.N%) 1 -ast-stats - Semi 32 (NN.N%) 1 -ast-stats - Expr 96 (NN.N%) 3 -ast-stats Block 192 (NN.N%) 6 32 -ast-stats FieldDef 208 (NN.N%) 2 104 -ast-stats Variant 208 (NN.N%) 2 104 -ast-stats AssocItem 320 (NN.N%) 4 80 -ast-stats - Fn 160 (NN.N%) 2 -ast-stats - Type 160 (NN.N%) 2 -ast-stats GenericBound 352 (NN.N%) 4 88 -ast-stats - Trait 352 (NN.N%) 4 -ast-stats GenericParam 480 (NN.N%) 5 96 -ast-stats Pat 504 (NN.N%) 7 72 -ast-stats - Struct 72 (NN.N%) 1 -ast-stats - Wild 72 (NN.N%) 1 -ast-stats - Ident 360 (NN.N%) 5 -ast-stats Expr 648 (NN.N%) 9 72 -ast-stats - InlineAsm 72 (NN.N%) 1 -ast-stats - Match 72 (NN.N%) 1 -ast-stats - Path 72 (NN.N%) 1 -ast-stats - Struct 72 (NN.N%) 1 -ast-stats - Lit 144 (NN.N%) 2 -ast-stats - Block 216 (NN.N%) 3 -ast-stats PathSegment 864 (NN.N%) 36 24 -ast-stats Ty 896 (NN.N%) 14 64 -ast-stats - Ptr 64 (NN.N%) 1 -ast-stats - Ref 64 (NN.N%) 1 -ast-stats - ImplicitSelf 128 (NN.N%) 2 -ast-stats - Path 640 (NN.N%) 10 ast-stats Item 1_584 (NN.N%) 11 144 ast-stats - Enum 144 (NN.N%) 1 ast-stats - ExternCrate 144 (NN.N%) 1 @@ -55,57 +10,61 @@ ast-stats - Impl 144 (NN.N%) 1 ast-stats - Trait 144 (NN.N%) 1 ast-stats - Fn 288 (NN.N%) 2 ast-stats - Use 576 (NN.N%) 4 +ast-stats Ty 896 (NN.N%) 14 64 +ast-stats - Ptr 64 (NN.N%) 1 +ast-stats - Ref 64 (NN.N%) 1 +ast-stats - ImplicitSelf 128 (NN.N%) 2 +ast-stats - Path 640 (NN.N%) 10 +ast-stats PathSegment 864 (NN.N%) 36 24 +ast-stats Expr 648 (NN.N%) 9 72 +ast-stats - InlineAsm 72 (NN.N%) 1 +ast-stats - Match 72 (NN.N%) 1 +ast-stats - Path 72 (NN.N%) 1 +ast-stats - Struct 72 (NN.N%) 1 +ast-stats - Lit 144 (NN.N%) 2 +ast-stats - Block 216 (NN.N%) 3 +ast-stats Pat 504 (NN.N%) 7 72 +ast-stats - Struct 72 (NN.N%) 1 +ast-stats - Wild 72 (NN.N%) 1 +ast-stats - Ident 360 (NN.N%) 5 +ast-stats GenericParam 480 (NN.N%) 5 96 +ast-stats GenericBound 352 (NN.N%) 4 88 +ast-stats - Trait 352 (NN.N%) 4 +ast-stats AssocItem 320 (NN.N%) 4 80 +ast-stats - Fn 160 (NN.N%) 2 +ast-stats - Type 160 (NN.N%) 2 +ast-stats Variant 208 (NN.N%) 2 104 +ast-stats FieldDef 208 (NN.N%) 2 104 +ast-stats Block 192 (NN.N%) 6 32 +ast-stats Stmt 160 (NN.N%) 5 32 +ast-stats - Let 32 (NN.N%) 1 +ast-stats - Semi 32 (NN.N%) 1 +ast-stats - Expr 96 (NN.N%) 3 +ast-stats Param 160 (NN.N%) 4 40 +ast-stats Attribute 128 (NN.N%) 4 32 +ast-stats - DocComment 32 (NN.N%) 1 +ast-stats - Normal 96 (NN.N%) 3 +ast-stats InlineAsm 120 (NN.N%) 1 120 +ast-stats FnDecl 120 (NN.N%) 5 24 +ast-stats Local 96 (NN.N%) 1 96 +ast-stats Arm 96 (NN.N%) 2 48 +ast-stats ForeignItem 80 (NN.N%) 1 80 +ast-stats - Fn 80 (NN.N%) 1 +ast-stats WherePredicate 72 (NN.N%) 1 72 +ast-stats - BoundPredicate 72 (NN.N%) 1 +ast-stats ExprField 48 (NN.N%) 1 48 +ast-stats GenericArgs 40 (NN.N%) 1 40 +ast-stats - AngleBracketed 40 (NN.N%) 1 +ast-stats Crate 40 (NN.N%) 1 40 ast-stats ---------------------------------------------------------------- ast-stats Total 7_416 127 -ast-stats -hir-stats HIR STATS +ast-stats ================================================================ +hir-stats ================================================================ +hir-stats HIR STATS: input_stats hir-stats Name Accumulated Size Count Item Size hir-stats ---------------------------------------------------------------- -hir-stats ForeignItemRef 24 (NN.N%) 1 24 -hir-stats Lifetime 28 (NN.N%) 1 28 -hir-stats Mod 32 (NN.N%) 1 32 -hir-stats ExprField 40 (NN.N%) 1 40 -hir-stats TraitItemRef 56 (NN.N%) 2 28 -hir-stats GenericArg 64 (NN.N%) 4 16 -hir-stats - Type 16 (NN.N%) 1 -hir-stats - Lifetime 48 (NN.N%) 3 -hir-stats Param 64 (NN.N%) 2 32 -hir-stats Body 72 (NN.N%) 3 24 -hir-stats ImplItemRef 72 (NN.N%) 2 36 -hir-stats InlineAsm 72 (NN.N%) 1 72 -hir-stats Local 72 (NN.N%) 1 72 -hir-stats WherePredicate 72 (NN.N%) 3 24 -hir-stats - BoundPredicate 72 (NN.N%) 3 -hir-stats Arm 80 (NN.N%) 2 40 -hir-stats Stmt 96 (NN.N%) 3 32 -hir-stats - Expr 32 (NN.N%) 1 -hir-stats - Let 32 (NN.N%) 1 -hir-stats - Semi 32 (NN.N%) 1 -hir-stats FnDecl 120 (NN.N%) 3 40 -hir-stats FieldDef 128 (NN.N%) 2 64 -hir-stats GenericArgs 144 (NN.N%) 3 48 -hir-stats Variant 144 (NN.N%) 2 72 -hir-stats Attribute 160 (NN.N%) 4 40 -hir-stats GenericBound 256 (NN.N%) 4 64 -hir-stats - Trait 256 (NN.N%) 4 -hir-stats Block 288 (NN.N%) 6 48 -hir-stats Pat 360 (NN.N%) 5 72 -hir-stats - Struct 72 (NN.N%) 1 -hir-stats - Wild 72 (NN.N%) 1 -hir-stats - Binding 216 (NN.N%) 3 -hir-stats GenericParam 400 (NN.N%) 5 80 -hir-stats Generics 560 (NN.N%) 10 56 -hir-stats Ty 720 (NN.N%) 15 48 -hir-stats - Ptr 48 (NN.N%) 1 -hir-stats - Ref 48 (NN.N%) 1 -hir-stats - Path 624 (NN.N%) 13 -hir-stats Expr 768 (NN.N%) 12 64 -hir-stats - InlineAsm 64 (NN.N%) 1 -hir-stats - Match 64 (NN.N%) 1 -hir-stats - Path 64 (NN.N%) 1 -hir-stats - Struct 64 (NN.N%) 1 -hir-stats - Lit 128 (NN.N%) 2 -hir-stats - Block 384 (NN.N%) 6 +hir-stats PathSegment 1_776 (NN.N%) 37 48 +hir-stats Path 1_040 (NN.N%) 26 40 hir-stats Item 968 (NN.N%) 11 88 hir-stats - Enum 88 (NN.N%) 1 hir-stats - ExternCrate 88 (NN.N%) 1 @@ -114,8 +73,51 @@ hir-stats - Impl 88 (NN.N%) 1 hir-stats - Trait 88 (NN.N%) 1 hir-stats - Fn 176 (NN.N%) 2 hir-stats - Use 352 (NN.N%) 4 -hir-stats Path 1_040 (NN.N%) 26 40 -hir-stats PathSegment 1_776 (NN.N%) 37 48 +hir-stats Expr 768 (NN.N%) 12 64 +hir-stats - InlineAsm 64 (NN.N%) 1 +hir-stats - Match 64 (NN.N%) 1 +hir-stats - Path 64 (NN.N%) 1 +hir-stats - Struct 64 (NN.N%) 1 +hir-stats - Lit 128 (NN.N%) 2 +hir-stats - Block 384 (NN.N%) 6 +hir-stats Ty 720 (NN.N%) 15 48 +hir-stats - Ptr 48 (NN.N%) 1 +hir-stats - Ref 48 (NN.N%) 1 +hir-stats - Path 624 (NN.N%) 13 +hir-stats Generics 560 (NN.N%) 10 56 +hir-stats GenericParam 400 (NN.N%) 5 80 +hir-stats Pat 360 (NN.N%) 5 72 +hir-stats - Struct 72 (NN.N%) 1 +hir-stats - Wild 72 (NN.N%) 1 +hir-stats - Binding 216 (NN.N%) 3 +hir-stats Block 288 (NN.N%) 6 48 +hir-stats GenericBound 256 (NN.N%) 4 64 +hir-stats - Trait 256 (NN.N%) 4 +hir-stats Attribute 160 (NN.N%) 4 40 +hir-stats Variant 144 (NN.N%) 2 72 +hir-stats GenericArgs 144 (NN.N%) 3 48 +hir-stats FieldDef 128 (NN.N%) 2 64 +hir-stats FnDecl 120 (NN.N%) 3 40 +hir-stats Stmt 96 (NN.N%) 3 32 +hir-stats - Expr 32 (NN.N%) 1 +hir-stats - Let 32 (NN.N%) 1 +hir-stats - Semi 32 (NN.N%) 1 +hir-stats Arm 80 (NN.N%) 2 40 +hir-stats WherePredicate 72 (NN.N%) 3 24 +hir-stats - BoundPredicate 72 (NN.N%) 3 +hir-stats Local 72 (NN.N%) 1 72 +hir-stats InlineAsm 72 (NN.N%) 1 72 +hir-stats ImplItemRef 72 (NN.N%) 2 36 +hir-stats Body 72 (NN.N%) 3 24 +hir-stats Param 64 (NN.N%) 2 32 +hir-stats GenericArg 64 (NN.N%) 4 16 +hir-stats - Type 16 (NN.N%) 1 +hir-stats - Lifetime 48 (NN.N%) 3 +hir-stats TraitItemRef 56 (NN.N%) 2 28 +hir-stats ExprField 40 (NN.N%) 1 40 +hir-stats Mod 32 (NN.N%) 1 32 +hir-stats Lifetime 28 (NN.N%) 1 28 +hir-stats ForeignItemRef 24 (NN.N%) 1 24 hir-stats ---------------------------------------------------------------- hir-stats Total 8_676 172 -hir-stats +hir-stats ================================================================ diff --git a/tests/ui/stats/macro-stats.stderr b/tests/ui/stats/macro-stats.stderr index f87e34622b92..00c6b55c6a23 100644 --- a/tests/ui/stats/macro-stats.stderr +++ b/tests/ui/stats/macro-stats.stderr @@ -2,25 +2,25 @@ macro-stats ==================================================================== macro-stats MACRO EXPANSION STATS: macro_stats macro-stats Macro Name Uses Lines Avg Lines Bytes Avg Bytes macro-stats ----------------------------------------------------------------------------------- -macro-stats #[derive(Clone)] 8 56 7.0 1_660 207.5 -macro-stats #[derive(PartialOrd)] 1 16 16.0 654 654.0 -macro-stats #[derive(Hash)] 2 15 7.5 547 273.5 -macro-stats #[derive(Ord)] 1 14 14.0 489 489.0 -macro-stats q! 1 24 24.0 435 435.0 -macro-stats #[derive(Default)] 2 14 7.0 367 183.5 -macro-stats #[derive(Eq)] 1 10 10.0 312 312.0 -macro-stats #[derive(Debug)] 1 7 7.0 261 261.0 -macro-stats #[derive(PartialEq)] 1 8 8.0 247 247.0 -macro-stats #[derive(Copy)] 1 1 1.0 46 46.0 -macro-stats p! 1 2 2.0 28 28.0 -macro-stats trait_impl_tys! 1 1 1.0 11 11.0 -macro-stats foreign_item! 1 0 0.0 6 6.0 -macro-stats impl_const! 1 0 0.0 4 4.0 -macro-stats trait_tys! 1 1 1.0 3 3.0 -macro-stats u32! 1 0 0.0 -3 -3.0 -macro-stats none! 1 0 0.0 -3 -3.0 -macro-stats n99! 2 0 0.0 -8 -4.0 +macro-stats #[derive(Clone)] 8 64 8.0 1_788 223.5 +macro-stats #[derive(PartialOrd)] 1 17 17.0 675 675.0 +macro-stats #[derive(Hash)] 2 17 8.5 577 288.5 +macro-stats q! 1 26 26.0 519 519.0 +macro-stats #[derive(Ord)] 1 15 15.0 503 503.0 +macro-stats #[derive(Default)] 2 16 8.0 403 201.5 +macro-stats #[derive(Eq)] 1 11 11.0 325 325.0 +macro-stats #[derive(Debug)] 1 8 8.0 277 277.0 +macro-stats #[derive(PartialEq)] 1 9 9.0 267 267.0 +macro-stats #[derive(Copy)] 1 2 2.0 61 61.0 +macro-stats p! 1 3 3.0 32 32.0 +macro-stats trait_impl_tys! 1 2 2.0 28 28.0 +macro-stats foreign_item! 1 1 1.0 21 21.0 macro-stats this_is_a_really_really_long_macro_name! -macro-stats 1 0 0.0 -30 -30.0 -macro-stats #[test] 1 -6 -6.0 -158 -158.0 +macro-stats 1 1 1.0 18 18.0 +macro-stats impl_const! 1 1 1.0 17 17.0 +macro-stats trait_tys! 1 2 2.0 15 15.0 +macro-stats n99! 2 2 1.0 4 2.0 +macro-stats none! 1 1 1.0 4 4.0 +macro-stats u32! 1 1 1.0 3 3.0 +macro-stats #[test] 1 1 1.0 0 0.0 macro-stats =================================================================================== diff --git a/tests/ui/suggestions/bound-suggestions.stderr b/tests/ui/suggestions/bound-suggestions.stderr index f23e086afe4e..ec1d23fac458 100644 --- a/tests/ui/suggestions/bound-suggestions.stderr +++ b/tests/ui/suggestions/bound-suggestions.stderr @@ -2,7 +2,9 @@ error[E0277]: `impl Sized` doesn't implement `Debug` --> $DIR/bound-suggestions.rs:9:22 | LL | println!("{:?}", t); - | ^ `impl Sized` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ---- ^ `impl Sized` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting opaque type `impl Sized` with trait `Debug` @@ -14,7 +16,9 @@ error[E0277]: `T` doesn't implement `Debug` --> $DIR/bound-suggestions.rs:15:22 | LL | println!("{:?}", t); - | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ---- ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` with trait `Debug` @@ -26,7 +30,9 @@ error[E0277]: `T` doesn't implement `Debug` --> $DIR/bound-suggestions.rs:21:22 | LL | println!("{:?}", t); - | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ---- ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `T` with trait `Debug` @@ -38,7 +44,9 @@ error[E0277]: `Y` doesn't implement `Debug` --> $DIR/bound-suggestions.rs:27:30 | LL | println!("{:?} {:?}", x, y); - | ^ `Y` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ---- ^ `Y` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `Y` with trait `Debug` @@ -50,7 +58,9 @@ error[E0277]: `X` doesn't implement `Debug` --> $DIR/bound-suggestions.rs:33:22 | LL | println!("{:?}", x); - | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ---- ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `X` with trait `Debug` @@ -62,7 +72,9 @@ error[E0277]: `X` doesn't implement `Debug` --> $DIR/bound-suggestions.rs:39:22 | LL | println!("{:?}", x); - | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ---- ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `X` with trait `Debug` diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.stderr b/tests/ui/suggestions/derive-macro-missing-bounds.stderr index 68c8204d1e18..b28f39ced542 100644 --- a/tests/ui/suggestions/derive-macro-missing-bounds.stderr +++ b/tests/ui/suggestions/derive-macro-missing-bounds.stderr @@ -4,9 +4,8 @@ error[E0277]: `a::Inner` doesn't implement `Debug` LL | #[derive(Debug)] | ----- in this derive macro expansion LL | struct Outer(Inner); - | ^^^^^^^^ `a::Inner` cannot be formatted using `{:?}` + | ^^^^^^^^ the trait `Debug` is not implemented for `a::Inner` | - = help: the trait `Debug` is not implemented for `a::Inner` = note: add `#[derive(Debug)]` to `a::Inner` or manually `impl Debug for a::Inner` help: consider annotating `a::Inner` with `#[derive(Debug)]` | diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs index 10b4781eb049..97a0e005f86a 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs @@ -4,19 +4,16 @@ trait A: Sized { fn f(a: A) -> A; //~^ ERROR expected a type, found a trait //~| ERROR expected a type, found a trait - //~| ERROR associated item referring to unboxed trait object for its own trait } trait B { fn f(b: B) -> B; //~^ ERROR expected a type, found a trait //~| ERROR expected a type, found a trait - //~| ERROR associated item referring to unboxed trait object for its own trait } trait C { fn f(&self, c: C) -> C; //~^ ERROR expected a type, found a trait //~| ERROR expected a type, found a trait - //~| ERROR associated item referring to unboxed trait object for its own trait } fn main() {} diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr index e189012d15c9..c4dab4691f49 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr @@ -26,22 +26,8 @@ help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as LL | fn f(a: A) -> impl A; | ++++ -error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 - | -LL | trait A: Sized { - | - in this trait -LL | fn f(a: A) -> A; - | ^ ^ - | -help: you might have meant to use `Self` to refer to the implementing type - | -LL - fn f(a: A) -> A; -LL + fn f(a: Self) -> Self; - | - error[E0782]: expected a type, found a trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:9:13 | LL | fn f(b: B) -> B; | ^ @@ -58,7 +44,7 @@ LL | fn f(b: impl B) -> B; | ++++ error[E0782]: expected a type, found a trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:19 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:9:19 | LL | fn f(b: B) -> B; | ^ @@ -68,22 +54,8 @@ help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as LL | fn f(b: B) -> impl B; | ++++ -error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 - | -LL | trait B { - | - in this trait -LL | fn f(b: B) -> B; - | ^ ^ - | -help: you might have meant to use `Self` to refer to the implementing type - | -LL - fn f(b: B) -> B; -LL + fn f(b: Self) -> Self; - | - error[E0782]: expected a type, found a trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:14:20 | LL | fn f(&self, c: C) -> C; | ^ @@ -100,7 +72,7 @@ LL | fn f(&self, c: impl C) -> C; | ++++ error[E0782]: expected a type, found a trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:26 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:14:26 | LL | fn f(&self, c: C) -> C; | ^ @@ -110,20 +82,6 @@ help: `C` is dyn-incompatible, use `impl C` to return an opaque type, as long as LL | fn f(&self, c: C) -> impl C; | ++++ -error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20 - | -LL | trait C { - | - in this trait -LL | fn f(&self, c: C) -> C; - | ^ ^ - | -help: you might have meant to use `Self` to refer to the implementing type - | -LL - fn f(&self, c: C) -> C; -LL + fn f(&self, c: Self) -> Self; - | - -error: aborting due to 9 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.rs index 747926c400ae..a798b1bd5787 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.rs +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.rs @@ -2,13 +2,11 @@ #![allow(bare_trait_objects)] trait A: Sized { fn f(a: dyn A) -> dyn A; - //~^ ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `A` is not dyn compatible + //~^ ERROR the trait `A` is not dyn compatible } trait B { fn f(a: dyn B) -> dyn B; - //~^ ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `B` is not dyn compatible + //~^ ERROR the trait `B` is not dyn compatible } trait C { fn f(&self, a: dyn C) -> dyn C; diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr index 2e3919db1b75..4ccf65b68bf7 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr @@ -1,17 +1,3 @@ -error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:4:13 - | -LL | trait A: Sized { - | - in this trait -LL | fn f(a: dyn A) -> dyn A; - | ^^^^^ ^^^^^ - | -help: you might have meant to use `Self` to refer to the implementing type - | -LL - fn f(a: dyn A) -> dyn A; -LL + fn f(a: Self) -> Self; - | - error[E0038]: the trait `A` is not dyn compatible --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:4:13 | @@ -26,30 +12,21 @@ LL | trait A: Sized { | - ^^^^^ ...because it requires `Self: Sized` | | | this trait is not dyn compatible... - -error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:9:13 - | -LL | trait B { - | - in this trait -LL | fn f(a: dyn B) -> dyn B; - | ^^^^^ ^^^^^ - | help: you might have meant to use `Self` to refer to the implementing type | -LL - fn f(a: dyn B) -> dyn B; -LL + fn f(a: Self) -> Self; +LL - fn f(a: dyn A) -> dyn A; +LL + fn f(a: Self) -> dyn A; | error[E0038]: the trait `B` is not dyn compatible - --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:9:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:8:13 | LL | fn f(a: dyn B) -> dyn B; | ^^^^^ `B` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:9:8 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:8:8 | LL | trait B { | - this trait is not dyn compatible... @@ -63,7 +40,12 @@ help: alternatively, consider constraining `f` so it does not apply to trait obj | LL | fn f(a: dyn B) -> dyn B where Self: Sized; | +++++++++++++++++ +help: you might have meant to use `Self` to refer to the implementing type + | +LL - fn f(a: dyn B) -> dyn B; +LL + fn f(a: Self) -> dyn B; + | -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.rs index 63fe5ebaea49..d8e9d381dbda 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.rs +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.rs @@ -1,12 +1,10 @@ trait A: Sized { fn f(a: dyn A) -> dyn A; - //~^ ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `A` is not dyn compatible + //~^ ERROR the trait `A` is not dyn compatible } trait B { fn f(a: dyn B) -> dyn B; - //~^ ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `B` is not dyn compatible + //~^ ERROR the trait `B` is not dyn compatible } trait C { fn f(&self, a: dyn C) -> dyn C; diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr index e8384afed7a1..bda1d01e23ff 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr @@ -1,17 +1,3 @@ -error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self.rs:2:13 - | -LL | trait A: Sized { - | - in this trait -LL | fn f(a: dyn A) -> dyn A; - | ^^^^^ ^^^^^ - | -help: you might have meant to use `Self` to refer to the implementing type - | -LL - fn f(a: dyn A) -> dyn A; -LL + fn f(a: Self) -> Self; - | - error[E0038]: the trait `A` is not dyn compatible --> $DIR/dyn-incompatible-trait-should-use-self.rs:2:13 | @@ -26,30 +12,21 @@ LL | trait A: Sized { | - ^^^^^ ...because it requires `Self: Sized` | | | this trait is not dyn compatible... - -error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self.rs:7:13 - | -LL | trait B { - | - in this trait -LL | fn f(a: dyn B) -> dyn B; - | ^^^^^ ^^^^^ - | help: you might have meant to use `Self` to refer to the implementing type | -LL - fn f(a: dyn B) -> dyn B; -LL + fn f(a: Self) -> Self; +LL - fn f(a: dyn A) -> dyn A; +LL + fn f(a: Self) -> dyn A; | error[E0038]: the trait `B` is not dyn compatible - --> $DIR/dyn-incompatible-trait-should-use-self.rs:7:13 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:6:13 | LL | fn f(a: dyn B) -> dyn B; | ^^^^^ `B` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/dyn-incompatible-trait-should-use-self.rs:7:8 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:6:8 | LL | trait B { | - this trait is not dyn compatible... @@ -63,7 +40,12 @@ help: alternatively, consider constraining `f` so it does not apply to trait obj | LL | fn f(a: dyn B) -> dyn B where Self: Sized; | +++++++++++++++++ +help: you might have meant to use `Self` to refer to the implementing type + | +LL - fn f(a: dyn B) -> dyn B; +LL + fn f(a: Self) -> dyn B; + | -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/impl-trait-with-missing-bounds.stderr b/tests/ui/suggestions/impl-trait-with-missing-bounds.stderr index d0ce7c9ed4e8..b3f1865dd309 100644 --- a/tests/ui/suggestions/impl-trait-with-missing-bounds.stderr +++ b/tests/ui/suggestions/impl-trait-with-missing-bounds.stderr @@ -2,11 +2,10 @@ error[E0277]: `::Item` doesn't implement `Debug` --> $DIR/impl-trait-with-missing-bounds.rs:6:13 | LL | qux(constraint); - | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | --- ^^^^^^^^^^ the trait `Debug` is not implemented for `::Item` | | | required by a bound introduced by this call | - = help: the trait `Debug` is not implemented for `::Item` note: required by a bound in `qux` --> $DIR/impl-trait-with-missing-bounds.rs:50:16 | @@ -22,11 +21,10 @@ error[E0277]: `::Item` doesn't implement `Debug` --> $DIR/impl-trait-with-missing-bounds.rs:14:13 | LL | qux(constraint); - | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | --- ^^^^^^^^^^ the trait `Debug` is not implemented for `::Item` | | | required by a bound introduced by this call | - = help: the trait `Debug` is not implemented for `::Item` note: required by a bound in `qux` --> $DIR/impl-trait-with-missing-bounds.rs:50:16 | @@ -42,11 +40,10 @@ error[E0277]: `::Item` doesn't implement `Debug` --> $DIR/impl-trait-with-missing-bounds.rs:22:13 | LL | qux(constraint); - | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | --- ^^^^^^^^^^ the trait `Debug` is not implemented for `::Item` | | | required by a bound introduced by this call | - = help: the trait `Debug` is not implemented for `::Item` note: required by a bound in `qux` --> $DIR/impl-trait-with-missing-bounds.rs:50:16 | @@ -62,11 +59,10 @@ error[E0277]: `::Item` doesn't implement `Debug` --> $DIR/impl-trait-with-missing-bounds.rs:30:13 | LL | qux(constraint); - | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | --- ^^^^^^^^^^ the trait `Debug` is not implemented for `::Item` | | | required by a bound introduced by this call | - = help: the trait `Debug` is not implemented for `::Item` note: required by a bound in `qux` --> $DIR/impl-trait-with-missing-bounds.rs:50:16 | @@ -82,11 +78,10 @@ error[E0277]: `::Item` doesn't impl --> $DIR/impl-trait-with-missing-bounds.rs:37:13 | LL | qux(constraint); - | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | --- ^^^^^^^^^^ the trait `Debug` is not implemented for `::Item` | | | required by a bound introduced by this call | - = help: the trait `Debug` is not implemented for `::Item` note: required by a bound in `qux` --> $DIR/impl-trait-with-missing-bounds.rs:50:16 | @@ -102,11 +97,10 @@ error[E0277]: `::Item` doesn't implement `Debug` --> $DIR/impl-trait-with-missing-bounds.rs:45:13 | LL | qux(constraint); - | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | --- ^^^^^^^^^^ the trait `Debug` is not implemented for `::Item` | | | required by a bound introduced by this call | - = help: the trait `Debug` is not implemented for `::Item` note: required by a bound in `qux` --> $DIR/impl-trait-with-missing-bounds.rs:50:16 | diff --git a/tests/ui/suggestions/issue-105645.rs b/tests/ui/suggestions/issue-105645.rs index 681ce1c6e37a..f3ca8ccbb3c7 100644 --- a/tests/ui/suggestions/issue-105645.rs +++ b/tests/ui/suggestions/issue-105645.rs @@ -2,7 +2,7 @@ fn main() { let mut buf = [0u8; 50]; let mut bref = buf.as_slice(); foo(&mut bref); - //~^ ERROR 4:9: 4:18: the trait bound `&[u8]: std::io::Write` is not satisfied [E0277] + //~^ ERROR the trait bound `&[u8]: std::io::Write` is not satisfied [E0277] } fn foo(_: &mut impl std::io::Write) {} diff --git a/tests/ui/suggestions/issue-116434-2015.rs b/tests/ui/suggestions/issue-116434-2015.rs index bad9d02321cf..e0438cdef253 100644 --- a/tests/ui/suggestions/issue-116434-2015.rs +++ b/tests/ui/suggestions/issue-116434-2015.rs @@ -11,6 +11,7 @@ trait Foo { //~| HELP if this is a dyn-compatible trait, use `dyn` //~| ERROR the trait `Clone` is not dyn compatible [E0038] //~| HELP there is an associated type with the same name + //~| HELP use `Self` to refer to the implementing type } trait DbHandle: Sized {} @@ -26,6 +27,7 @@ trait DbInterface { //~| HELP if this is a dyn-compatible trait, use `dyn` //~| ERROR the trait `DbHandle` is not dyn compatible [E0038] //~| HELP there is an associated type with the same name + //~| HELP use `Self` to refer to the implementing type } fn main() {} diff --git a/tests/ui/suggestions/issue-116434-2015.stderr b/tests/ui/suggestions/issue-116434-2015.stderr index a0a99cc560db..cad5812da663 100644 --- a/tests/ui/suggestions/issue-116434-2015.stderr +++ b/tests/ui/suggestions/issue-116434-2015.stderr @@ -35,13 +35,18 @@ LL | fn foo() -> Clone; = note: the trait is not dyn compatible because it requires `Self: Sized` = note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit +help: you might have meant to use `Self` to refer to the implementing type + | +LL - fn foo() -> Clone; +LL + fn foo() -> Self; + | help: there is an associated type with the same name | LL | fn foo() -> Self::Clone; | ++++++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-116434-2015.rs:20:20 + --> $DIR/issue-116434-2015.rs:21:20 | LL | fn handle() -> DbHandle; | ^^^^^^^^ @@ -54,7 +59,7 @@ LL | fn handle() -> dyn DbHandle; | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-116434-2015.rs:20:20 + --> $DIR/issue-116434-2015.rs:21:20 | LL | fn handle() -> DbHandle; | ^^^^^^^^ @@ -68,19 +73,24 @@ LL | fn handle() -> dyn DbHandle; | +++ error[E0038]: the trait `DbHandle` is not dyn compatible - --> $DIR/issue-116434-2015.rs:20:20 + --> $DIR/issue-116434-2015.rs:21:20 | LL | fn handle() -> DbHandle; | ^^^^^^^^ `DbHandle` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/issue-116434-2015.rs:16:17 + --> $DIR/issue-116434-2015.rs:17:17 | LL | trait DbHandle: Sized {} | -------- ^^^^^ ...because it requires `Self: Sized` | | | this trait is not dyn compatible... +help: you might have meant to use `Self` to refer to the implementing type + | +LL - fn handle() -> DbHandle; +LL + fn handle() -> Self; + | help: there is an associated type with the same name | LL | fn handle() -> Self::DbHandle; diff --git a/tests/ui/suggestions/issue-81098.stderr b/tests/ui/suggestions/issue-81098.stderr index 4dc47a202824..36948469a311 100644 --- a/tests/ui/suggestions/issue-81098.stderr +++ b/tests/ui/suggestions/issue-81098.stderr @@ -2,23 +2,17 @@ error[E0277]: `()` doesn't implement `std::fmt::Display` --> $DIR/issue-81098.rs:3:13 | LL | fn wat() -> impl core::fmt::Display { - | ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter - | - = help: the trait `std::fmt::Display` is not implemented for `()` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::fmt::Display` is not implemented for `()` error[E0277]: `()` doesn't implement `std::fmt::Display` --> $DIR/issue-81098.rs:9:12 | LL | fn ok() -> impl core::fmt::Display { - | ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::fmt::Display` is not implemented for `()` LL | 1; | -- help: remove this semicolon | | | this expression has type `{integer}`, which implements `std::fmt::Display` - | - = help: the trait `std::fmt::Display` is not implemented for `()` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/issue-97760.stderr b/tests/ui/suggestions/issue-97760.stderr index c3cf7e13987b..1084ea7c9e0e 100644 --- a/tests/ui/suggestions/issue-97760.stderr +++ b/tests/ui/suggestions/issue-97760.stderr @@ -1,8 +1,11 @@ error[E0277]: `::Item` doesn't implement `std::fmt::Display` - --> $DIR/issue-97760.rs:4:19 + --> $DIR/issue-97760.rs:4:20 | LL | println!("{x}"); - | ^^^ `::Item` cannot be formatted with the default formatter + | -^- + | || + | |`::Item` cannot be formatted with the default formatter + | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `::Item` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index 3f8b6f93e1f4..e3375b67c86d 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -21,7 +21,7 @@ error[E0277]: `K` doesn't implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:14 | LL | pub loc: Vector2, - | ^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^ the trait `Debug` is not implemented for `K` | note: required by a bound in `Vector2` --> $DIR/missing-bound-in-derive-copy-impl-3.rs:5:23 @@ -40,7 +40,7 @@ LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion LL | pub struct AABB{ LL | pub loc: Vector2, - | ^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `K` | help: consider further restricting type parameter `K` with trait `Debug` | @@ -54,7 +54,7 @@ LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion ... LL | pub size: Vector2 - | ^^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `K` | help: consider further restricting type parameter `K` with trait `Debug` | diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 3766e3e2c7b5..645d6ebb3961 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -21,7 +21,7 @@ error[E0277]: `K` doesn't implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl.rs:11:14 | LL | pub loc: Vector2, - | ^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^ the trait `Debug` is not implemented for `K` | note: required by a bound in `Vector2` --> $DIR/missing-bound-in-derive-copy-impl.rs:4:23 @@ -78,7 +78,7 @@ LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion LL | pub struct AABB { LL | pub loc: Vector2, - | ^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `K` | help: consider restricting type parameter `K` with trait `Debug` | @@ -111,7 +111,7 @@ LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion ... LL | pub size: Vector2, - | ^^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `K` | help: consider restricting type parameter `K` with trait `Debug` | diff --git a/tests/ui/suggestions/path-display.stderr b/tests/ui/suggestions/path-display.stderr index 46d0b35825bc..0c7271b3c1c3 100644 --- a/tests/ui/suggestions/path-display.stderr +++ b/tests/ui/suggestions/path-display.stderr @@ -2,18 +2,23 @@ error[E0277]: `Path` doesn't implement `std::fmt::Display` --> $DIR/path-display.rs:5:20 | LL | println!("{}", path); - | ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it + | -- ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it + | | + | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `Path` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data + = note: required for `&Path` to implement `std::fmt::Display` = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `PathBuf` doesn't implement `std::fmt::Display` --> $DIR/path-display.rs:9:20 | LL | println!("{}", path); - | ^^^^ `PathBuf` cannot be formatted with the default formatter; call `.display()` on it + | -- ^^^^ `PathBuf` cannot be formatted with the default formatter; call `.display()` on it + | | + | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `PathBuf` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead diff --git a/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs index 1dfc0786668f..807fba0ab7e7 100644 --- a/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs +++ b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs @@ -6,5 +6,5 @@ mod option { } fn main() { - let _: option::O<()> = (); //~ ERROR 9:28: 9:30: mismatched types [E0308] + let _: option::O<()> = (); //~ ERROR mismatched types [E0308] } diff --git a/tests/ui/syntax-extension-minor.rs b/tests/ui/syntax-extension-minor.rs deleted file mode 100644 index 826990a89a53..000000000000 --- a/tests/ui/syntax-extension-minor.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ run-pass - -#![feature(concat_idents)] -#![expect(deprecated)] // concat_idents is deprecated - -pub fn main() { - struct Foo; - let _: concat_idents!(F, oo) = Foo; // Test that `concat_idents!` can be used in type positions - - let asdf_fdsa = "<.<".to_string(); - // concat_idents should have call-site hygiene. - assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string()); - - assert_eq!(stringify!(use_mention_distinction), "use_mention_distinction"); -} diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.riscv.stderr b/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.riscv.stderr index 2dca0c220332..0b2d71f97d0d 100644 --- a/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.riscv.stderr +++ b/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.riscv.stderr @@ -7,13 +7,5 @@ warning: unstable feature specified for `-Ctarget-feature`: `d` | = note: this feature is not stably supported; its behavior can change in the future -warning: unstable feature specified for `-Ctarget-feature`: `f` - | - = note: this feature is not stably supported; its behavior can change in the future - -warning: unstable feature specified for `-Ctarget-feature`: `zicsr` - | - = note: this feature is not stably supported; its behavior can change in the future - -warning: 4 warnings emitted +warning: 2 warnings emitted diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.rs b/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.rs index 302cceccf693..1006b078bab3 100644 --- a/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.rs +++ b/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.rs @@ -24,5 +24,3 @@ pub trait Freeze {} //~? WARN must be disabled to ensure that the ABI of the current target can be implemented correctly //~? WARN unstable feature specified for `-Ctarget-feature` -//[riscv]~? WARN unstable feature specified for `-Ctarget-feature` -//[riscv]~? WARN unstable feature specified for `-Ctarget-feature` diff --git a/tests/ui/target-feature/retpoline-target-feature-flag.by_feature1.stderr b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature1.stderr index 2a0f5f01aef6..79e89823c517 100644 --- a/tests/ui/target-feature/retpoline-target-feature-flag.by_feature1.stderr +++ b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature1.stderr @@ -1,4 +1,4 @@ -warning: target feature `retpoline-external-thunk` cannot be enabled with `-Ctarget-feature`: use `retpoline-external-thunk` target modifier flag instead +warning: target feature `retpoline-external-thunk` cannot be enabled with `-Ctarget-feature`: use `-Zretpoline-external-thunk` compiler flag instead | = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #116344 diff --git a/tests/ui/target-feature/retpoline-target-feature-flag.by_feature2.stderr b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature2.stderr index f7b6cb164477..f5ff15df6329 100644 --- a/tests/ui/target-feature/retpoline-target-feature-flag.by_feature2.stderr +++ b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature2.stderr @@ -1,4 +1,4 @@ -warning: target feature `retpoline-indirect-branches` cannot be enabled with `-Ctarget-feature`: use `retpoline` target modifier flag instead +warning: target feature `retpoline-indirect-branches` cannot be enabled with `-Ctarget-feature`: use `-Zretpoline` compiler flag instead | = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #116344 diff --git a/tests/ui/target-feature/retpoline-target-feature-flag.by_feature3.stderr b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature3.stderr index 4f2cd1d1a522..158cca08a762 100644 --- a/tests/ui/target-feature/retpoline-target-feature-flag.by_feature3.stderr +++ b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature3.stderr @@ -1,4 +1,4 @@ -warning: target feature `retpoline-indirect-calls` cannot be enabled with `-Ctarget-feature`: use `retpoline` target modifier flag instead +warning: target feature `retpoline-indirect-calls` cannot be enabled with `-Ctarget-feature`: use `-Zretpoline` compiler flag instead | = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #116344 diff --git a/tests/ui/target-feature/retpoline-target-feature-flag.rs b/tests/ui/target-feature/retpoline-target-feature-flag.rs index de3c44c3ed0e..05c85860385a 100644 --- a/tests/ui/target-feature/retpoline-target-feature-flag.rs +++ b/tests/ui/target-feature/retpoline-target-feature-flag.rs @@ -16,6 +16,6 @@ #![no_core] extern crate minicore; -//[by_feature1]~? WARN target feature `retpoline-external-thunk` cannot be enabled with `-Ctarget-feature`: use `retpoline-external-thunk` target modifier flag instead -//[by_feature2]~? WARN target feature `retpoline-indirect-branches` cannot be enabled with `-Ctarget-feature`: use `retpoline` target modifier flag instead -//[by_feature3]~? WARN target feature `retpoline-indirect-calls` cannot be enabled with `-Ctarget-feature`: use `retpoline` target modifier flag instead +//[by_feature1]~? WARN target feature `retpoline-external-thunk` cannot be enabled with `-Ctarget-feature` +//[by_feature2]~? WARN target feature `retpoline-indirect-branches` cannot be enabled with `-Ctarget-feature` +//[by_feature3]~? WARN target feature `retpoline-indirect-calls` cannot be enabled with `-Ctarget-feature` diff --git a/tests/ui/thir-print/thir-tree-loop-match.rs b/tests/ui/thir-print/thir-tree-loop-match.rs new file mode 100644 index 000000000000..8c5f2244d546 --- /dev/null +++ b/tests/ui/thir-print/thir-tree-loop-match.rs @@ -0,0 +1,22 @@ +//@ check-pass +//@ compile-flags: -Zunpretty=thir-tree + +#![allow(incomplete_features)] +#![feature(loop_match)] + +fn boolean(mut state: bool) -> bool { + #[loop_match] + loop { + state = 'blk: { + match state { + true => { + #[const_continue] + break 'blk false; + } + false => return state, + } + } + } +} + +fn main() {} diff --git a/tests/ui/thir-print/thir-tree-loop-match.stdout b/tests/ui/thir-print/thir-tree-loop-match.stdout new file mode 100644 index 000000000000..828b93da6beb --- /dev/null +++ b/tests/ui/thir-print/thir-tree-loop-match.stdout @@ -0,0 +1,301 @@ +DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean): +params: [ + Param { + ty: bool + ty_span: Some($DIR/thir-tree-loop-match.rs:7:23: 7:27 (#0)) + self_kind: None + hir_id: Some(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).1)) + param: Some( + Pat: { + ty: bool + span: $DIR/thir-tree-loop-match.rs:7:12: 7:21 (#0) + kind: PatKind { + Binding { + name: "state" + mode: BindingMode(No, Mut) + var: LocalVarId(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).2)) + ty: bool + is_primary: true + subpattern: None + } + } + } + ) + } +] +body: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(28)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:7:37: 20:2 (#0) + kind: + Scope { + region_scope: Node(28) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).28)) + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(28)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:7:37: 20:2 (#0) + kind: + Block { + targeted_by_break: false + span: $DIR/thir-tree-loop-match.rs:7:37: 20:2 (#0) + region_scope: Node(3) + safety_mode: Safe + stmts: [] + expr: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(28)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:9:5: 19:6 (#0) + kind: + Scope { + region_scope: Node(4) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).4)) + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(28)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:9:5: 19:6 (#0) + kind: + NeverToAny { + source: + Expr { + ty: ! + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(28)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:9:5: 19:6 (#0) + kind: + LoopMatch { + state: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(5)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:10:9: 10:14 (#0) + kind: + Scope { + region_scope: Node(7) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).7)) + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(5)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:10:9: 10:14 (#0) + kind: + VarRef { + id: LocalVarId(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).2)) + } + } + } + } + region_scope: Node(10) + match_span: $DIR/thir-tree-loop-match.rs:11:13: 17:14 (#0) + arms: [ + Arm { + pattern: + Pat: { + ty: bool + span: $DIR/thir-tree-loop-match.rs:12:17: 12:21 (#0) + kind: PatKind { + Constant { + value: Ty(bool, true) + } + } + } + guard: None + body: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(16)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:12:25: 15:18 (#0) + kind: + Scope { + region_scope: Node(17) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).17)) + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(16)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:12:25: 15:18 (#0) + kind: + NeverToAny { + source: + Expr { + ty: ! + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(16)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:12:25: 15:18 (#0) + kind: + Block { + targeted_by_break: false + span: $DIR/thir-tree-loop-match.rs:12:25: 15:18 (#0) + region_scope: Node(18) + safety_mode: Safe + stmts: [ + Stmt { + kind: Expr { + scope: Node(21) + expr: + Expr { + ty: ! + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(21)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:14:21: 14:37 (#0) + kind: + Scope { + region_scope: Node(19) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).19)) + value: + Expr { + ty: ! + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(21)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:14:21: 14:37 (#0) + kind: + ConstContinue ( + label: Node(10) + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(21)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:14:32: 14:37 (#0) + kind: + Scope { + region_scope: Node(20) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).20)) + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(21)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:14:32: 14:37 (#0) + kind: + Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-loop-match.rs:14:32: 14:37 (#0) }, neg: false) + + } + } + } + ) + } + } + } + } + } + ] + expr: [] + } + } + } + } + } + } + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).16)) + scope: Node(16) + span: $DIR/thir-tree-loop-match.rs:12:17: 15:18 (#0) + } + Arm { + pattern: + Pat: { + ty: bool + span: $DIR/thir-tree-loop-match.rs:16:17: 16:22 (#0) + kind: PatKind { + Constant { + value: Ty(bool, false) + } + } + } + guard: None + body: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:16:26: 16:38 (#0) + kind: + Scope { + region_scope: Node(25) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).25)) + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:16:26: 16:38 (#0) + kind: + NeverToAny { + source: + Expr { + ty: ! + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:16:26: 16:38 (#0) + kind: + Return { + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:16:33: 16:38 (#0) + kind: + Scope { + region_scope: Node(26) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).26)) + value: + Expr { + ty: bool + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:16:33: 16:38 (#0) + kind: + VarRef { + id: LocalVarId(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).2)) + } + } + } + } + } + } + } + } + } + } + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree_loop_match[3c53]::boolean).24)) + scope: Node(24) + span: $DIR/thir-tree-loop-match.rs:16:17: 16:38 (#0) + } + ] + } + } + } + } + } + } + } + } + } + } + + +DefId(0:4 ~ thir_tree_loop_match[3c53]::main): +params: [ +] +body: + Expr { + ty: () + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:22:11: 22:13 (#0) + kind: + Scope { + region_scope: Node(2) + lint_level: Explicit(HirId(DefId(0:4 ~ thir_tree_loop_match[3c53]::main).2)) + value: + Expr { + ty: () + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None } + span: $DIR/thir-tree-loop-match.rs:22:11: 22:13 (#0) + kind: + Block { + targeted_by_break: false + span: $DIR/thir-tree-loop-match.rs:22:11: 22:13 (#0) + region_scope: Node(1) + safety_mode: Safe + stmts: [] + expr: [] + } + } + } + } + + diff --git a/tests/ui/traits/const-traits/call-const-trait-method-pass.rs b/tests/ui/traits/const-traits/call-const-trait-method-pass.rs index 3004647ede07..d66a11490c59 100644 --- a/tests/ui/traits/const-traits/call-const-trait-method-pass.rs +++ b/tests/ui/traits/const-traits/call-const-trait-method-pass.rs @@ -1,6 +1,5 @@ -//@ known-bug: #110395 - #![feature(const_trait_impl, const_ops)] +//@ check-pass struct Int(i32); diff --git a/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr b/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr deleted file mode 100644 index 7746f103ac36..000000000000 --- a/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/call-const-trait-method-pass.rs:15:12 - | -LL | impl const PartialEq for Int { - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error[E0015]: cannot call non-const method `::eq` in constant functions - --> $DIR/call-const-trait-method-pass.rs:20:15 - | -LL | !self.eq(other) - | ^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-in-impl.rs b/tests/ui/traits/const-traits/call-generic-in-impl.rs index 6149dc3d1263..b63458b39e95 100644 --- a/tests/ui/traits/const-traits/call-generic-in-impl.rs +++ b/tests/ui/traits/const-traits/call-generic-in-impl.rs @@ -1,5 +1,4 @@ -//@ known-bug: #110395 -// FIXME(const_trait_impl) check-pass +//@ check-pass #![feature(const_trait_impl)] #[const_trait] diff --git a/tests/ui/traits/const-traits/call-generic-in-impl.stderr b/tests/ui/traits/const-traits/call-generic-in-impl.stderr deleted file mode 100644 index a45dfd95b4a4..000000000000 --- a/tests/ui/traits/const-traits/call-generic-in-impl.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-in-impl.rs:10:9 - | -LL | impl const MyPartialEq for T { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-in-impl.rs:10:9 - | -LL | impl const MyPartialEq for T { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const method `::eq` in constant functions - --> $DIR/call-generic-in-impl.rs:12:9 - | -LL | PartialEq::eq(self, other) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-method-chain.rs b/tests/ui/traits/const-traits/call-generic-method-chain.rs index 74beab71208a..b515c0e711da 100644 --- a/tests/ui/traits/const-traits/call-generic-method-chain.rs +++ b/tests/ui/traits/const-traits/call-generic-method-chain.rs @@ -1,8 +1,7 @@ //! Basic test for calling methods on generic type parameters in `const fn`. -//@ known-bug: #110395 //@ compile-flags: -Znext-solver -// FIXME(const_trait_impl) check-pass +//@ check-pass #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/call-generic-method-chain.stderr b/tests/ui/traits/const-traits/call-generic-method-chain.stderr deleted file mode 100644 index 40b4f14733f0..000000000000 --- a/tests/ui/traits/const-traits/call-generic-method-chain.stderr +++ /dev/null @@ -1,66 +0,0 @@ -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/call-generic-method-chain.rs:11:12 - | -LL | impl const PartialEq for S { - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-chain.rs:20:25 - | -LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-chain.rs:20:25 - | -LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-chain.rs:24:33 - | -LL | const fn equals_self_wrapper(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-chain.rs:24:33 - | -LL | const fn equals_self_wrapper(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/call-generic-method-chain.rs:21:5 - | -LL | *t == *t - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const method `::eq` in constant functions - --> $DIR/call-generic-method-chain.rs:16:15 - | -LL | !self.eq(other) - | ^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 7 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs b/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs index ec615d8484cd..fdc439845ace 100644 --- a/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs +++ b/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -//@ known-bug: #110395 -// FIXME(const_trait_impl) check-pass +//@ check-pass #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr deleted file mode 100644 index c74f5cf786c1..000000000000 --- a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr +++ /dev/null @@ -1,74 +0,0 @@ -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/call-generic-method-dup-bound.rs:9:12 - | -LL | impl const PartialEq for S { - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-dup-bound.rs:20:37 - | -LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-dup-bound.rs:20:37 - | -LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-dup-bound.rs:27:30 - | -LL | const fn equals_self2(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-dup-bound.rs:27:30 - | -LL | const fn equals_self2(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/call-generic-method-dup-bound.rs:21:5 - | -LL | *t == *t - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const method `::eq` in constant functions - --> $DIR/call-generic-method-dup-bound.rs:14:15 - | -LL | !self.eq(other) - | ^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/call-generic-method-dup-bound.rs:28:5 - | -LL | *t == *t - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 8 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-method-fail.rs b/tests/ui/traits/const-traits/call-generic-method-fail.rs index 66881334a298..3ab5cc58ce3c 100644 --- a/tests/ui/traits/const-traits/call-generic-method-fail.rs +++ b/tests/ui/traits/const-traits/call-generic-method-fail.rs @@ -3,7 +3,7 @@ pub const fn equals_self(t: &T) -> bool { *t == *t - //~^ ERROR cannot call non-const operator in constant functions + //~^ ERROR the trait bound `T: ~const PartialEq` is not satisfied } fn main() {} diff --git a/tests/ui/traits/const-traits/call-generic-method-fail.stderr b/tests/ui/traits/const-traits/call-generic-method-fail.stderr index 6bacb986fef0..9facf80ee876 100644 --- a/tests/ui/traits/const-traits/call-generic-method-fail.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-fail.stderr @@ -1,11 +1,9 @@ -error[E0015]: cannot call non-const operator in constant functions +error[E0277]: the trait bound `T: ~const PartialEq` is not satisfied --> $DIR/call-generic-method-fail.rs:5:5 | LL | *t == *t | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.rs b/tests/ui/traits/const-traits/call-generic-method-pass.rs index af793b8da031..bc671c897f07 100644 --- a/tests/ui/traits/const-traits/call-generic-method-pass.rs +++ b/tests/ui/traits/const-traits/call-generic-method-pass.rs @@ -1,8 +1,7 @@ //! Basic test for calling methods on generic type parameters in `const fn`. //@ compile-flags: -Znext-solver -//@ known-bug: #110395 -// FIXME(const_trait_impl) check-pass +//@ check-pass #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.stderr b/tests/ui/traits/const-traits/call-generic-method-pass.stderr deleted file mode 100644 index 1a33ff5ab450..000000000000 --- a/tests/ui/traits/const-traits/call-generic-method-pass.stderr +++ /dev/null @@ -1,47 +0,0 @@ -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/call-generic-method-pass.rs:11:12 - | -LL | impl const PartialEq for S { - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-pass.rs:20:25 - | -LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-pass.rs:20:25 - | -LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/call-generic-method-pass.rs:21:5 - | -LL | *t == *t - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const method `::eq` in constant functions - --> $DIR/call-generic-method-pass.rs:16:15 - | -LL | !self.eq(other) - | ^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-impl-trait.stderr b/tests/ui/traits/const-traits/const-impl-trait.stderr index 6783cec3960d..ee922f9689ed 100644 --- a/tests/ui/traits/const-traits/const-impl-trait.stderr +++ b/tests/ui/traits/const-traits/const-impl-trait.stderr @@ -1,197 +1,17 @@ -error[E0635]: unknown feature `const_cmp` - --> $DIR/const-impl-trait.rs:7:30 +error[E0277]: the trait bound `(): const PartialEq` is not satisfied + --> $DIR/const-impl-trait.rs:34:17 | -LL | #![feature(const_trait_impl, const_cmp, const_destruct)] - | ^^^^^^^^^ - -error: `~const` can only be applied to `#[const_trait]` traits +LL | assert!(cmp(&())); + | --- ^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `cmp` --> $DIR/const-impl-trait.rs:11:23 | LL | const fn cmp(a: &impl ~const PartialEq) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL + | ^^^^^^^^^^^^^^^^ required by this bound in `cmp` -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:11:23 - | -LL | const fn cmp(a: &impl ~const PartialEq) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: aborting due to 1 previous error -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:16:13 - | -LL | x: impl ~const PartialEq + ~const Destruct, - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:16:13 - | -LL | x: impl ~const PartialEq + ~const Destruct, - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:17:11 - | -LL | ) -> impl ~const PartialEq + ~const Destruct { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:17:11 - | -LL | ) -> impl ~const PartialEq + ~const Destruct { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:23:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:27:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:17:11 - | -LL | ) -> impl ~const PartialEq + ~const Destruct { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:27:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:27:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:23:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:23:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:23:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:23:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:23:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const operator in constants - --> $DIR/const-impl-trait.rs:35:13 - | -LL | assert!(wrap(123) == wrap(123)); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const operator in constants - --> $DIR/const-impl-trait.rs:36:13 - | -LL | assert!(wrap(123) != wrap(456)); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const operator in constants - --> $DIR/const-impl-trait.rs:38:13 - | -LL | assert!(x == x); - | ^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/const-impl-trait.rs:12:5 - | -LL | a == a - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 21 previous errors - -Some errors have detailed explanations: E0015, E0635. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs index b563b78f78a1..f90ff91aff4b 100644 --- a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs +++ b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs @@ -6,7 +6,6 @@ // Regression test for issue #125877. //@ compile-flags: -Znext-solver -//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION" #![feature(const_trait_impl, effects)] //~^ ERROR feature has been removed diff --git a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr index a04f98e68a63..566961b27f3a 100644 --- a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr +++ b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr @@ -1,14 +1,14 @@ error[E0557]: feature has been removed - --> $DIR/const-trait-impl-parameter-mismatch.rs:11:30 + --> $DIR/const-trait-impl-parameter-mismatch.rs:10:30 | LL | #![feature(const_trait_impl, effects)] | ^^^^^^^ feature has been removed | - = note: removed in 1.84.0 (you are using $RUSTC_VERSION); see for more information + = note: removed in 1.84.0; see for more information = note: removed, redundant with `#![feature(const_trait_impl)]` error[E0049]: associated function `compute` has 0 type parameters but its trait declaration has 1 type parameter - --> $DIR/const-trait-impl-parameter-mismatch.rs:20:16 + --> $DIR/const-trait-impl-parameter-mismatch.rs:19:16 | LL | fn compute() -> u32; | - expected 1 type parameter diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr index 8297911a3f3c..87ac78908bba 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr @@ -1,9 +1,3 @@ -error[E0635]: unknown feature `const_cmp` - --> $DIR/derive-const-use.rs:3:30 - | -LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)] - | ^^^^^^^^^ - error[E0635]: unknown feature `const_default_impls` --> $DIR/derive-const-use.rs:3:41 | @@ -28,23 +22,13 @@ LL | #[derive_const(Default, PartialEq)] = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/derive-const-use.rs:11:12 - | -LL | impl const PartialEq for A { - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/derive-const-use.rs:15:25 +error[E0277]: the trait bound `(): ~const PartialEq` is not satisfied + --> $DIR/derive-const-use.rs:16:14 | LL | #[derive_const(Default, PartialEq)] - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change + | --------- in this derive macro expansion +LL | pub struct S((), A); + | ^^ error[E0015]: cannot call non-const associated function `::default` in constants --> $DIR/derive-const-use.rs:18:35 @@ -54,14 +38,6 @@ LL | const _: () = assert!(S((), A) == S::default()); | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const operator in constants - --> $DIR/derive-const-use.rs:18:23 - | -LL | const _: () = assert!(S((), A) == S::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - error[E0015]: cannot call non-const associated function `<() as Default>::default` in constant functions --> $DIR/derive-const-use.rs:16:14 | @@ -82,27 +58,7 @@ LL | pub struct S((), A); | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/derive-const-use.rs:16:14 - | -LL | #[derive_const(Default, PartialEq)] - | --------- in this derive macro expansion -LL | pub struct S((), A); - | ^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +error: aborting due to 7 previous errors -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/derive-const-use.rs:16:18 - | -LL | #[derive_const(Default, PartialEq)] - | --------- in this derive macro expansion -LL | pub struct S((), A); - | ^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 12 previous errors - -Some errors have detailed explanations: E0015, E0635. +Some errors have detailed explanations: E0015, E0277, E0635. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs index 18b224af2780..b39f97b59382 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs +++ b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs @@ -1,5 +1,4 @@ -//@ known-bug: #110395 -// FIXME(const_trait_impl) check-pass +//@ check-pass #![feature(derive_const)] #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr deleted file mode 100644 index d1dbf62d5666..000000000000 --- a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr +++ /dev/null @@ -1,35 +0,0 @@ -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/derive-const-with-params.rs:7:16 - | -LL | #[derive_const(PartialEq)] - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error: `~const` can only be applied to `#[const_trait]` traits - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/derive-const-with-params.rs:8:23 - | -LL | #[derive_const(PartialEq)] - | --------- in this derive macro expansion -LL | pub struct Reverse(T); - | ^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/derive-const-with-params.rs:11:5 - | -LL | a == b - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs index 4cb013b93230..4312d295b113 100644 --- a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs +++ b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs @@ -11,7 +11,6 @@ const fn test() -> impl ~const Fn() { [first, remainder @ ..] => { assert_eq!(first, &b'f'); //~^ ERROR cannot call non-const function - //~| ERROR cannot call non-const operator } [] => panic!(), } diff --git a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr index 8d9371bf9f69..f06bacdeb4e2 100644 --- a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr +++ b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr @@ -37,15 +37,6 @@ note: `Fn` can't be used with `~const` because it isn't annotated with `#[const_ --> $SRC_DIR/core/src/ops/function.rs:LL:COL = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/ice-112822-expected-type-for-param.rs:12:17 - | -LL | assert_eq!(first, &b'f'); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) - error[E0015]: cannot call non-const function `core::panicking::assert_failed::<&u8, &u8>` in constant functions --> $DIR/ice-112822-expected-type-for-param.rs:12:17 | @@ -55,7 +46,7 @@ LL | assert_eq!(first, &b'f'); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0015, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/on_unimplemented_long_types.stderr b/tests/ui/traits/on_unimplemented_long_types.stderr index 1628466e0818..f32d99a42b12 100644 --- a/tests/ui/traits/on_unimplemented_long_types.stderr +++ b/tests/ui/traits/on_unimplemented_long_types.stderr @@ -2,7 +2,7 @@ error[E0277]: `Option>>` doesn't implement `std::fmt::Display --> $DIR/on_unimplemented_long_types.rs:3:17 | LL | pub fn foo() -> impl std::fmt::Display { - | ^^^^^^^^^^^^^^^^^^^^^^ `Option>>` cannot be formatted with the default formatter + | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound LL | LL | / Some(Some(Some(Some(Some(Some(Some(Some(Some(S... LL | | Some(Some(Some(Some(Some(Some(Some(Some(So... @@ -14,7 +14,6 @@ LL | | ))))))))))) | |_______________- return type was inferred to be `Option>>` here | = help: the trait `std::fmt::Display` is not implemented for `Option>>` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: the full name for the type has been written to '$TEST_BUILD_DIR/on_unimplemented_long_types.long-type-$LONG_TYPE_HASH.txt' = note: consider using `--verbose` to print the full type name to the console diff --git a/tests/ui/traits/suggest-remove-deref-issue-140166.stderr b/tests/ui/traits/suggest-remove-deref-issue-140166.stderr index 90f24d86d53e..7c61f957fdcc 100644 --- a/tests/ui/traits/suggest-remove-deref-issue-140166.stderr +++ b/tests/ui/traits/suggest-remove-deref-issue-140166.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `&Chars: Trait` is not satisfied LL | format_args!("{:?}", FlatMap(&Chars)); | ---- ^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `&Chars` | | - | required by a bound introduced by this call + | required by this formatting parameter | = help: the trait `Trait` is implemented for `Chars` note: required for `FlatMap<&Chars>` to implement `Debug` @@ -14,8 +14,6 @@ LL | impl std::fmt::Debug for FlatMap { | ----- ^^^^^^^^^^^^^^^ ^^^^^^^^^^ | | | unsatisfied trait bound introduced here -note: required by a bound in `core::fmt::rt::Argument::<'_>::new_debug` - --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/traits/trait-object-destructure.rs b/tests/ui/traits/trait-object-destructure.rs new file mode 100644 index 000000000000..6c091677c8ce --- /dev/null +++ b/tests/ui/traits/trait-object-destructure.rs @@ -0,0 +1,29 @@ +//! Regression test for destructuring trait references (`&dyn T`/`Box`). +//! Checks cases where number of `&`/`Box` patterns (n) matches/doesn't match references (m). +//! +//! Issue: https://github.com/rust-lang/rust/issues/15031 + +#![feature(box_patterns)] + +trait T { + fn foo(&self) {} +} + +impl T for isize {} + +fn main() { + // Valid cases: n < m (can dereference) + let &x = &(&1isize as &dyn T); + let &x = &&(&1isize as &dyn T); + let &&x = &&(&1isize as &dyn T); + + // Error cases: n == m (cannot dereference trait object) + let &x = &1isize as &dyn T; //~ ERROR type `&dyn T` cannot be dereferenced + let &&x = &(&1isize as &dyn T); //~ ERROR type `&dyn T` cannot be dereferenced + let box x = Box::new(1isize) as Box; //~ ERROR type `Box` cannot be dereferenced + + // Error cases: n > m (type mismatch) + let &&x = &1isize as &dyn T; //~ ERROR mismatched types + let &&&x = &(&1isize as &dyn T); //~ ERROR mismatched types + let box box x = Box::new(1isize) as Box; //~ ERROR mismatched types +} diff --git a/tests/ui/destructure-trait-ref.stderr b/tests/ui/traits/trait-object-destructure.stderr similarity index 87% rename from tests/ui/destructure-trait-ref.stderr rename to tests/ui/traits/trait-object-destructure.stderr index 0b5ea551a578..c7c832dc40af 100644 --- a/tests/ui/destructure-trait-ref.stderr +++ b/tests/ui/traits/trait-object-destructure.stderr @@ -1,23 +1,23 @@ error[E0033]: type `&dyn T` cannot be dereferenced - --> $DIR/destructure-trait-ref.rs:28:9 + --> $DIR/trait-object-destructure.rs:21:9 | LL | let &x = &1isize as &dyn T; | ^^ type `&dyn T` cannot be dereferenced error[E0033]: type `&dyn T` cannot be dereferenced - --> $DIR/destructure-trait-ref.rs:29:10 + --> $DIR/trait-object-destructure.rs:22:10 | LL | let &&x = &(&1isize as &dyn T); | ^^ type `&dyn T` cannot be dereferenced error[E0033]: type `Box` cannot be dereferenced - --> $DIR/destructure-trait-ref.rs:30:9 + --> $DIR/trait-object-destructure.rs:23:9 | LL | let box x = Box::new(1isize) as Box; | ^^^^^ type `Box` cannot be dereferenced error[E0308]: mismatched types - --> $DIR/destructure-trait-ref.rs:34:10 + --> $DIR/trait-object-destructure.rs:26:10 | LL | let &&x = &1isize as &dyn T; | ^^ ----------------- this expression has type `&dyn T` @@ -33,7 +33,7 @@ LL + let &x = &1isize as &dyn T; | error[E0308]: mismatched types - --> $DIR/destructure-trait-ref.rs:38:11 + --> $DIR/trait-object-destructure.rs:27:11 | LL | let &&&x = &(&1isize as &dyn T); | ^^ -------------------- this expression has type `&&dyn T` @@ -49,7 +49,7 @@ LL + let &&x = &(&1isize as &dyn T); | error[E0308]: mismatched types - --> $DIR/destructure-trait-ref.rs:42:13 + --> $DIR/trait-object-destructure.rs:28:13 | LL | let box box x = Box::new(1isize) as Box; | ^^^^^ ------------------------------ this expression has type `Box` diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr index c0f6d6780976..01d24cabf48d 100644 --- a/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr @@ -2,9 +2,8 @@ error[E0277]: `T` doesn't implement `std::fmt::Display` --> $DIR/bounds-are-checked3.rs:9:35 | LL | type Foo = (impl Debug, Struct); - | ^^^^^^^^^ `T` cannot be formatted with the default formatter + | ^^^^^^^^^ the trait `std::fmt::Display` is not implemented for `T` | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `Struct` --> $DIR/bounds-are-checked3.rs:5:18 | diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr index ef0e73f1481f..193f0c92c9de 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr @@ -2,7 +2,7 @@ error[E0277]: `T` doesn't implement `Debug` --> $DIR/generic_duplicate_param_use2.rs:12:5 | LL | t - | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^ the trait `Debug` is not implemented for `T` | note: required by a bound in an opaque type --> $DIR/generic_duplicate_param_use2.rs:8:23 diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr index 0932c72ff934..f0d1e93b0b76 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr @@ -2,7 +2,7 @@ error[E0277]: `U` doesn't implement `Debug` --> $DIR/generic_duplicate_param_use4.rs:12:5 | LL | u - | ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^ the trait `Debug` is not implemented for `U` | note: required by a bound in an opaque type --> $DIR/generic_duplicate_param_use4.rs:8:23 diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr index 429c3b9175a5..1e3c454a5bc2 100644 --- a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr @@ -2,7 +2,7 @@ error[E0277]: `U` doesn't implement `Debug` --> $DIR/generic_underconstrained2.rs:9:33 | LL | fn underconstrained(_: U) -> Underconstrained { - | ^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `U` | note: required by a bound on the type alias `Underconstrained` --> $DIR/generic_underconstrained2.rs:5:26 @@ -18,7 +18,7 @@ error[E0277]: `V` doesn't implement `Debug` --> $DIR/generic_underconstrained2.rs:19:43 | LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { - | ^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `V` | note: required by a bound on the type alias `Underconstrained2` --> $DIR/generic_underconstrained2.rs:15:27 @@ -34,7 +34,7 @@ error[E0277]: `U` doesn't implement `Debug` --> $DIR/generic_underconstrained2.rs:9:33 | LL | fn underconstrained(_: U) -> Underconstrained { - | ^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `U` | note: required by a bound on the type alias `Underconstrained` --> $DIR/generic_underconstrained2.rs:5:26 @@ -51,7 +51,7 @@ error[E0277]: `V` doesn't implement `Debug` --> $DIR/generic_underconstrained2.rs:19:43 | LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { - | ^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `V` | note: required by a bound on the type alias `Underconstrained2` --> $DIR/generic_underconstrained2.rs:15:27 diff --git a/tests/ui/type-alias-impl-trait/nested.stderr b/tests/ui/type-alias-impl-trait/nested.stderr index 59911f65a234..f72830b864d1 100644 --- a/tests/ui/type-alias-impl-trait/nested.stderr +++ b/tests/ui/type-alias-impl-trait/nested.stderr @@ -15,7 +15,9 @@ error[E0277]: `Bar` doesn't implement `Debug` --> $DIR/nested.rs:17:22 | LL | println!("{:?}", bar()); - | ^^^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ---- ^^^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter | = help: the trait `Debug` is not implemented for `Bar` = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/type/binding-assigned-block-without-tail-expression.stderr b/tests/ui/type/binding-assigned-block-without-tail-expression.stderr index 3e96d7f317b4..ff34facf3892 100644 --- a/tests/ui/type/binding-assigned-block-without-tail-expression.stderr +++ b/tests/ui/type/binding-assigned-block-without-tail-expression.stderr @@ -5,7 +5,9 @@ LL | 42; | - help: remove this semicolon ... LL | println!("{}", x); - | ^ `()` cannot be formatted with the default formatter + | -- ^ `()` cannot be formatted with the default formatter + | | + | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead @@ -18,7 +20,9 @@ LL | let y = {}; | -- this empty block is missing a tail expression ... LL | println!("{}", y); - | ^ `()` cannot be formatted with the default formatter + | -- ^ `()` cannot be formatted with the default formatter + | | + | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead @@ -31,7 +35,9 @@ LL | "hi"; | - help: remove this semicolon ... LL | println!("{}", z); - | ^ `()` cannot be formatted with the default formatter + | -- ^ `()` cannot be formatted with the default formatter + | | + | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead @@ -47,7 +53,9 @@ LL | | }; | |_____- this block is missing a tail expression ... LL | println!("{}", s); - | ^ `()` cannot be formatted with the default formatter + | -- ^ `()` cannot be formatted with the default formatter + | | + | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead diff --git a/tests/ui/type/option-ref-advice.rs b/tests/ui/type/option-ref-advice.rs index 2dcee5a2eb91..435b15d01e3c 100644 --- a/tests/ui/type/option-ref-advice.rs +++ b/tests/ui/type/option-ref-advice.rs @@ -3,9 +3,9 @@ fn takes_option(_arg: Option<&String>) {} fn main() { - takes_option(&None); //~ ERROR 6:18: 6:23: mismatched types [E0308] + takes_option(&None); //~ ERROR mismatched types [E0308] let x = String::from("x"); let res = Some(x); - takes_option(&res); //~ ERROR 10:18: 10:22: mismatched types [E0308] + takes_option(&res); //~ ERROR mismatched types [E0308] } diff --git a/tests/ui/type/pattern_types/derives_fail.stderr b/tests/ui/type/pattern_types/derives_fail.stderr index 78bef726341d..6b2e27494f0e 100644 --- a/tests/ui/type/pattern_types/derives_fail.stderr +++ b/tests/ui/type/pattern_types/derives_fail.stderr @@ -26,9 +26,7 @@ LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default) | ----- in this derive macro expansion LL | #[repr(transparent)] LL | struct Nanoseconds(NanoI32); - | ^^^^^^^ `(i32) is 0..=999999999` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = help: the trait `Debug` is not implemented for `(i32) is 0..=999999999` + | ^^^^^^^ the trait `Debug` is not implemented for `(i32) is 0..=999999999` error[E0277]: the trait bound `(i32) is 0..=999999999: Ord` is not satisfied --> $DIR/derives_fail.rs:11:20 diff --git a/tests/ui/typeck/auxiliary/private-dep.rs b/tests/ui/typeck/auxiliary/private-dep.rs new file mode 100644 index 000000000000..472b40ef6229 --- /dev/null +++ b/tests/ui/typeck/auxiliary/private-dep.rs @@ -0,0 +1,3 @@ +pub trait A { + fn foo() {} +} diff --git a/tests/ui/typeck/auxiliary/public-dep.rs b/tests/ui/typeck/auxiliary/public-dep.rs new file mode 100644 index 000000000000..438692a1caa3 --- /dev/null +++ b/tests/ui/typeck/auxiliary/public-dep.rs @@ -0,0 +1,11 @@ +//@ aux-crate:priv:private_dep=private-dep.rs +//@ compile-flags: -Zunstable-options + +extern crate private_dep; +use private_dep::A; + +pub struct B; + +impl A for B { + fn foo() {} +} diff --git a/tests/ui/typeck/dont-suggest-private-dependencies.rs b/tests/ui/typeck/dont-suggest-private-dependencies.rs new file mode 100644 index 000000000000..ee5224e2d821 --- /dev/null +++ b/tests/ui/typeck/dont-suggest-private-dependencies.rs @@ -0,0 +1,37 @@ +// Don't suggest importing a function from a private dependency. +// Issues: #138191, #142676 + +// Avoid suggesting traits from std-private deps +//@ forbid-output: compiler_builtins +//@ forbid-output: object + +// Check a custom trait to withstand changes in above crates +//@ aux-crate:public_dep=public-dep.rs +//@ compile-flags: -Zunstable-options +//@ forbid-output: private_dep + +// By default, the `read` diagnostic suggests `std::os::unix::fs::FileExt::read_at`. Add +// something more likely to be recommended to make the diagnostic cross-platform. +trait DecoyRead { + fn read1(&self) {} +} +impl DecoyRead for Vec {} + +struct VecReader(Vec); + +impl std::io::Read for VecReader { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + self.0.read(buf) + //~^ ERROR no method named `read` found for struct `Vec` + } +} + +extern crate public_dep; +use public_dep::B; + +fn main() { + let _ = u8::cast_from_lossy(9); + //~^ ERROR no function or associated item named `cast_from_lossy` found for type `u8` + let _ = B::foo(); + //~^ ERROR no function or associated item named `foo` found for struct `B` +} diff --git a/tests/ui/typeck/dont-suggest-private-dependencies.stderr b/tests/ui/typeck/dont-suggest-private-dependencies.stderr new file mode 100644 index 000000000000..b7b14ee6b9bb --- /dev/null +++ b/tests/ui/typeck/dont-suggest-private-dependencies.stderr @@ -0,0 +1,27 @@ +error[E0599]: no method named `read` found for struct `Vec` in the current scope + --> $DIR/dont-suggest-private-dependencies.rs:24:16 + | +LL | self.0.read(buf) + | ^^^^ + | +help: there is a method `read1` with a similar name, but with different arguments + --> $DIR/dont-suggest-private-dependencies.rs:16:5 + | +LL | fn read1(&self) {} + | ^^^^^^^^^^^^^^^ + +error[E0599]: no function or associated item named `cast_from_lossy` found for type `u8` in the current scope + --> $DIR/dont-suggest-private-dependencies.rs:33:17 + | +LL | let _ = u8::cast_from_lossy(9); + | ^^^^^^^^^^^^^^^ function or associated item not found in `u8` + +error[E0599]: no function or associated item named `foo` found for struct `B` in the current scope + --> $DIR/dont-suggest-private-dependencies.rs:35:16 + | +LL | let _ = B::foo(); + | ^^^ function or associated item not found in `B` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/inference-method-chain-diverging-fallback.rs b/tests/ui/typeck/inference-method-chain-diverging-fallback.rs new file mode 100644 index 000000000000..8f549b7d9d68 --- /dev/null +++ b/tests/ui/typeck/inference-method-chain-diverging-fallback.rs @@ -0,0 +1,19 @@ +//! Test type inference in method chains with diverging fallback. +//! Verifies that closure type in `unwrap_or_else` is properly inferred +//! when chained with other combinators and contains a diverging path. + +//@ run-pass + +fn produce() -> Result<&'static str, T> { + Ok("22") +} + +fn main() { + // The closure's error type `T` must unify with `ParseIntError`, + // while the success type must be `usize` (from parse()) + let x: usize = produce() + .and_then(|x| x.parse::()) // Explicit turbofish for clarity + .unwrap_or_else(|_| panic!()); // Diverging fallback + + assert_eq!(x, 22); +} diff --git a/tests/ui/typeck/issue-100246.rs b/tests/ui/typeck/issue-100246.rs index 8f0b34bab0c8..e05bb2a1362a 100644 --- a/tests/ui/typeck/issue-100246.rs +++ b/tests/ui/typeck/issue-100246.rs @@ -25,6 +25,6 @@ fn downcast<'a, W: ?Sized>() -> std::io::Result<&'a W> { struct Other; fn main() -> std::io::Result<()> { - let other: Other = downcast()?;//~ERROR 28:24: 28:35: `?` operator has incompatible types + let other: Other = downcast()?; //~ ERROR `?` operator has incompatible types Ok(()) } diff --git a/tests/ui/typeck/issue-89275.rs b/tests/ui/typeck/issue-89275.rs index b91c00175487..6e4211de1857 100644 --- a/tests/ui/typeck/issue-89275.rs +++ b/tests/ui/typeck/issue-89275.rs @@ -25,5 +25,5 @@ fn downcast<'a, W: ?Sized>() -> &'a W { struct Other; fn main() { - let other: &mut Other = downcast();//~ERROR 28:29: 28:39: mismatched types [E0308] + let other: &mut Other = downcast();//~ ERROR mismatched types [E0308] } diff --git a/tests/ui/typeck/point-at-type-param-in-path-expr.stderr b/tests/ui/typeck/point-at-type-param-in-path-expr.stderr index 14642b25c994..3701b3e37988 100644 --- a/tests/ui/typeck/point-at-type-param-in-path-expr.stderr +++ b/tests/ui/typeck/point-at-type-param-in-path-expr.stderr @@ -2,10 +2,8 @@ error[E0277]: `()` doesn't implement `std::fmt::Display` --> $DIR/point-at-type-param-in-path-expr.rs:4:19 | LL | let x = foo::<()>; - | ^^ `()` cannot be formatted with the default formatter + | ^^ the trait `std::fmt::Display` is not implemented for `()` | - = help: the trait `std::fmt::Display` is not implemented for `()` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `foo` --> $DIR/point-at-type-param-in-path-expr.rs:1:11 | diff --git a/tests/ui/underscore-imports/issue-110164.stderr b/tests/ui/underscore-imports/issue-110164.ed2015.stderr similarity index 56% rename from tests/ui/underscore-imports/issue-110164.stderr rename to tests/ui/underscore-imports/issue-110164.ed2015.stderr index d8a4b6bbb754..f34b5ab5dde7 100644 --- a/tests/ui/underscore-imports/issue-110164.stderr +++ b/tests/ui/underscore-imports/issue-110164.ed2015.stderr @@ -1,17 +1,17 @@ error: expected identifier, found reserved identifier `_` - --> $DIR/issue-110164.rs:5:5 + --> $DIR/issue-110164.rs:8:5 | LL | use _::a; | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/issue-110164.rs:8:5 + --> $DIR/issue-110164.rs:10:5 | LL | use _::*; | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/issue-110164.rs:13:9 + --> $DIR/issue-110164.rs:14:9 | LL | use _::a; | ^ expected identifier, found reserved identifier @@ -23,41 +23,17 @@ LL | use _::*; | ^ expected identifier, found reserved identifier error[E0432]: unresolved import `self::*` - --> $DIR/issue-110164.rs:1:5 + --> $DIR/issue-110164.rs:4:5 | LL | use self::*; | ^^^^^^^ cannot glob-import a module into itself error[E0432]: unresolved import `crate::*` - --> $DIR/issue-110164.rs:3:5 + --> $DIR/issue-110164.rs:6:5 | LL | use crate::*; | ^^^^^^^^ cannot glob-import a module into itself -error[E0432]: unresolved import `_` - --> $DIR/issue-110164.rs:8:5 - | -LL | use _::*; - | ^ `_` is not a valid crate or module name - -error[E0432]: unresolved import `_` - --> $DIR/issue-110164.rs:5:5 - | -LL | use _::a; - | ^ `_` is not a valid crate or module name - -error[E0432]: unresolved import `_` - --> $DIR/issue-110164.rs:13:9 - | -LL | use _::a; - | ^ `_` is not a valid crate or module name - -error[E0432]: unresolved import `_` - --> $DIR/issue-110164.rs:16:9 - | -LL | use _::*; - | ^ `_` is not a valid crate or module name - -error: aborting due to 10 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/underscore-imports/issue-110164.ed2021.stderr b/tests/ui/underscore-imports/issue-110164.ed2021.stderr new file mode 100644 index 000000000000..f34b5ab5dde7 --- /dev/null +++ b/tests/ui/underscore-imports/issue-110164.ed2021.stderr @@ -0,0 +1,39 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/issue-110164.rs:8:5 + | +LL | use _::a; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/issue-110164.rs:10:5 + | +LL | use _::*; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/issue-110164.rs:14:9 + | +LL | use _::a; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/issue-110164.rs:16:9 + | +LL | use _::*; + | ^ expected identifier, found reserved identifier + +error[E0432]: unresolved import `self::*` + --> $DIR/issue-110164.rs:4:5 + | +LL | use self::*; + | ^^^^^^^ cannot glob-import a module into itself + +error[E0432]: unresolved import `crate::*` + --> $DIR/issue-110164.rs:6:5 + | +LL | use crate::*; + | ^^^^^^^^ cannot glob-import a module into itself + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/underscore-imports/issue-110164.rs b/tests/ui/underscore-imports/issue-110164.rs index 6fd13414500d..bb080c5e471d 100644 --- a/tests/ui/underscore-imports/issue-110164.rs +++ b/tests/ui/underscore-imports/issue-110164.rs @@ -1,19 +1,18 @@ +//@ revisions: ed2015 ed2021 +//@[ed2015] edition: 2015 +//@[ed2021] edition: 2021 use self::*; //~^ ERROR unresolved import `self::*` use crate::*; //~^ ERROR unresolved import `crate::*` use _::a; //~^ ERROR expected identifier, found reserved identifier `_` -//~| ERROR unresolved import `_` use _::*; //~^ ERROR expected identifier, found reserved identifier `_` -//~| ERROR unresolved import `_` fn main() { use _::a; //~^ ERROR expected identifier, found reserved identifier `_` - //~| ERROR unresolved import `_` use _::*; //~^ ERROR expected identifier, found reserved identifier `_` - //~| ERROR unresolved import `_` } diff --git a/tests/ui/underscore-imports/multiple-uses.ed2015.stderr b/tests/ui/underscore-imports/multiple-uses.ed2015.stderr new file mode 100644 index 000000000000..a295586fa16f --- /dev/null +++ b/tests/ui/underscore-imports/multiple-uses.ed2015.stderr @@ -0,0 +1,49 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/multiple-uses.rs:4:9 + | +LL | pub use _::{a, b}; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/multiple-uses.rs:6:18 + | +LL | pub use std::{a, _}; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/multiple-uses.rs:9:18 + | +LL | pub use std::{b, _, c}; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/multiple-uses.rs:12:15 + | +LL | pub use std::{_, d}; + | ^ expected identifier, found reserved identifier + +error[E0432]: unresolved import `std::a` + --> $DIR/multiple-uses.rs:6:15 + | +LL | pub use std::{a, _}; + | ^ no `a` in the root + +error[E0432]: unresolved imports `std::b`, `std::c` + --> $DIR/multiple-uses.rs:9:15 + | +LL | pub use std::{b, _, c}; + | ^ ^ + | | | + | | no `c` in the root + | | help: a similar name exists in the module: `rc` + | no `b` in the root + +error[E0432]: unresolved import `std::d` + --> $DIR/multiple-uses.rs:12:18 + | +LL | pub use std::{_, d}; + | ^ no `d` in the root + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/underscore-imports/multiple-uses.ed2021.stderr b/tests/ui/underscore-imports/multiple-uses.ed2021.stderr new file mode 100644 index 000000000000..a295586fa16f --- /dev/null +++ b/tests/ui/underscore-imports/multiple-uses.ed2021.stderr @@ -0,0 +1,49 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/multiple-uses.rs:4:9 + | +LL | pub use _::{a, b}; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/multiple-uses.rs:6:18 + | +LL | pub use std::{a, _}; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/multiple-uses.rs:9:18 + | +LL | pub use std::{b, _, c}; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/multiple-uses.rs:12:15 + | +LL | pub use std::{_, d}; + | ^ expected identifier, found reserved identifier + +error[E0432]: unresolved import `std::a` + --> $DIR/multiple-uses.rs:6:15 + | +LL | pub use std::{a, _}; + | ^ no `a` in the root + +error[E0432]: unresolved imports `std::b`, `std::c` + --> $DIR/multiple-uses.rs:9:15 + | +LL | pub use std::{b, _, c}; + | ^ ^ + | | | + | | no `c` in the root + | | help: a similar name exists in the module: `rc` + | no `b` in the root + +error[E0432]: unresolved import `std::d` + --> $DIR/multiple-uses.rs:12:18 + | +LL | pub use std::{_, d}; + | ^ no `d` in the root + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/underscore-imports/multiple-uses.rs b/tests/ui/underscore-imports/multiple-uses.rs new file mode 100644 index 000000000000..31dd1862429e --- /dev/null +++ b/tests/ui/underscore-imports/multiple-uses.rs @@ -0,0 +1,16 @@ +//@ revisions: ed2015 ed2021 +//@[ed2015] edition: 2015 +//@[ed2021] edition: 2021 +pub use _::{a, b}; +//~^ ERROR expected identifier, found reserved identifier `_` +pub use std::{a, _}; +//~^ ERROR expected identifier, found reserved identifier `_` +//~| ERROR unresolved import `std::a` +pub use std::{b, _, c}; +//~^ ERROR expected identifier, found reserved identifier `_` +//~| ERROR unresolved imports `std::b`, `std::c` +pub use std::{_, d}; +//~^ ERROR expected identifier, found reserved identifier `_` +//~| ERROR unresolved import `std::d` + +fn main() {} diff --git a/tests/ui/unpretty/deprecated-attr.rs b/tests/ui/unpretty/deprecated-attr.rs index 0c80203e9652..e2ab5efb5d87 100644 --- a/tests/ui/unpretty/deprecated-attr.rs +++ b/tests/ui/unpretty/deprecated-attr.rs @@ -16,3 +16,8 @@ pub struct SinceAndNote; #[deprecated(note = "here's why this is deprecated", since = "1.2.3")] pub struct FlippedOrder; + +pub fn f() { + // Attribute is ignored here (with a warning), but still preserved in HIR + #[deprecated] 0 +} diff --git a/tests/ui/unpretty/deprecated-attr.stdout b/tests/ui/unpretty/deprecated-attr.stdout index 97d863b2e943..a2b645d00d06 100644 --- a/tests/ui/unpretty/deprecated-attr.stdout +++ b/tests/ui/unpretty/deprecated-attr.stdout @@ -24,3 +24,12 @@ struct SinceAndNote; #[attr = Deprecation {deprecation: Deprecation {since: NonStandard("1.2.3"), note: "here's why this is deprecated"}}] struct FlippedOrder; + +fn f() { + + // Attribute is ignored here (with a warning), but still preserved in HIR + #[attr = Deprecation {deprecation: + Deprecation {since: + Unspecified}}] + 0 +} diff --git a/tests/ui/unpretty/diagnostic-attr.stdout b/tests/ui/unpretty/diagnostic-attr.stdout index 81d71b91d815..3b15a845d68f 100644 --- a/tests/ui/unpretty/diagnostic-attr.stdout +++ b/tests/ui/unpretty/diagnostic-attr.stdout @@ -12,6 +12,4 @@ extern crate std; trait ImportantTrait { } #[diagnostic::do_not_recommend] -impl ImportantTrait for T where T: Clone - {#![diagnostic::do_not_recommend] -} +impl ImportantTrait for T where T: Clone { } diff --git a/tests/ui/unpretty/exhaustive-asm.hir.stdout b/tests/ui/unpretty/exhaustive-asm.hir.stdout index 810db69bff16..ec9bda573312 100644 --- a/tests/ui/unpretty/exhaustive-asm.hir.stdout +++ b/tests/ui/unpretty/exhaustive-asm.hir.stdout @@ -26,7 +26,7 @@ mod expressions { mod items { /// ItemKind::GlobalAsm - mod item_global_asm {/// ItemKind::GlobalAsm + mod item_global_asm { global_asm! (".globl my_asm_func"); } } diff --git a/tests/ui/unpretty/exhaustive.expanded.stdout b/tests/ui/unpretty/exhaustive.expanded.stdout index cd1a5d0af08a..ae44d1206afa 100644 --- a/tests/ui/unpretty/exhaustive.expanded.stdout +++ b/tests/ui/unpretty/exhaustive.expanded.stdout @@ -12,7 +12,6 @@ #![feature(auto_traits)] #![feature(box_patterns)] #![feature(builtin_syntax)] -#![feature(concat_idents)] #![feature(const_trait_impl)] #![feature(decl_macro)] #![feature(deref_patterns)] @@ -309,7 +308,6 @@ mod expressions { - // concat_idents is deprecated @@ -622,8 +620,12 @@ mod types { /*! there is no syntax for this */ } /// TyKind::MacCall - #[expect(deprecated)] - fn ty_mac_call() { let _: T; let _: T; let _: T; } + fn ty_mac_call() { + macro_rules! ty { ($ty:ty) => { $ty } } + let _: T; + let _: T; + let _: T; + } /// TyKind::CVarArgs fn ty_c_var_args() { /*! FIXME: todo */ diff --git a/tests/ui/unpretty/exhaustive.hir.stderr b/tests/ui/unpretty/exhaustive.hir.stderr index 58f7ff0f5981..1c78cf98c59f 100644 --- a/tests/ui/unpretty/exhaustive.hir.stderr +++ b/tests/ui/unpretty/exhaustive.hir.stderr @@ -1,17 +1,17 @@ error[E0697]: closures cannot be static - --> $DIR/exhaustive.rs:211:9 + --> $DIR/exhaustive.rs:210:9 | LL | static || value; | ^^^^^^^^^ error[E0697]: closures cannot be static - --> $DIR/exhaustive.rs:212:9 + --> $DIR/exhaustive.rs:211:9 | LL | static move || value; | ^^^^^^^^^^^^^^ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/exhaustive.rs:241:13 + --> $DIR/exhaustive.rs:240:13 | LL | fn expr_await() { | --------------- this is not `async` @@ -20,19 +20,19 @@ LL | fut.await; | ^^^^^ only allowed inside `async` functions and blocks error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/exhaustive.rs:290:9 + --> $DIR/exhaustive.rs:289:9 | LL | _; | ^ `_` not allowed here error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:300:9 + --> $DIR/exhaustive.rs:299:9 | LL | x::(); | ^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:301:9 + --> $DIR/exhaustive.rs:300:9 | LL | x::(T, T) -> T; | ^^^^^^^^^^^^^^ only `Fn` traits may use parentheses @@ -44,31 +44,31 @@ LL + x:: -> T; | error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:302:9 + --> $DIR/exhaustive.rs:301:9 | LL | crate::() -> ()::expressions::() -> ()::expr_path; | ^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:302:26 + --> $DIR/exhaustive.rs:301:26 | LL | crate::() -> ()::expressions::() -> ()::expr_path; | ^^^^^^^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:305:9 + --> $DIR/exhaustive.rs:304:9 | LL | core::()::marker::()::PhantomData; | ^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:305:19 + --> $DIR/exhaustive.rs:304:19 | LL | core::()::marker::()::PhantomData; | ^^^^^^^^^^ only `Fn` traits may use parentheses error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks - --> $DIR/exhaustive.rs:392:9 + --> $DIR/exhaustive.rs:391:9 | LL | yield; | ^^^^^ @@ -79,7 +79,7 @@ LL | #[coroutine] fn expr_yield() { | ++++++++++++ error[E0703]: invalid ABI: found `C++` - --> $DIR/exhaustive.rs:472:23 + --> $DIR/exhaustive.rs:471:23 | LL | unsafe extern "C++" {} | ^^^^^ invalid ABI @@ -87,7 +87,7 @@ LL | unsafe extern "C++" {} = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions error: `..` patterns are not allowed here - --> $DIR/exhaustive.rs:679:13 + --> $DIR/exhaustive.rs:678:13 | LL | let ..; | ^^ @@ -95,13 +95,13 @@ LL | let ..; = note: only allowed in tuple, tuple struct, and slice patterns error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:794:16 + --> $DIR/exhaustive.rs:793:16 | LL | let _: T() -> !; | ^^^^^^^^ only `Fn` traits may use parentheses error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:809:16 + --> $DIR/exhaustive.rs:808:16 | LL | let _: impl Send; | ^^^^^^^^^ @@ -112,7 +112,7 @@ LL | let _: impl Send; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:810:16 + --> $DIR/exhaustive.rs:809:16 | LL | let _: impl Send + 'static; | ^^^^^^^^^^^^^^^^^^^ @@ -123,7 +123,7 @@ LL | let _: impl Send + 'static; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:811:16 + --> $DIR/exhaustive.rs:810:16 | LL | let _: impl 'static + Send; | ^^^^^^^^^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL | let _: impl 'static + Send; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:812:16 + --> $DIR/exhaustive.rs:811:16 | LL | let _: impl ?Sized; | ^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL | let _: impl ?Sized; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:813:16 + --> $DIR/exhaustive.rs:812:16 | LL | let _: impl ~const Clone; | ^^^^^^^^^^^^^^^^^ @@ -156,7 +156,7 @@ LL | let _: impl ~const Clone; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:814:16 + --> $DIR/exhaustive.rs:813:16 | LL | let _: impl for<'a> Send; | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unpretty/exhaustive.hir.stdout b/tests/ui/unpretty/exhaustive.hir.stdout index c20f123b16e8..2d347ec6e88d 100644 --- a/tests/ui/unpretty/exhaustive.hir.stdout +++ b/tests/ui/unpretty/exhaustive.hir.stdout @@ -11,7 +11,6 @@ #![feature(auto_traits)] #![feature(box_patterns)] #![feature(builtin_syntax)] -#![feature(concat_idents)] #![feature(const_trait_impl)] #![feature(decl_macro)] #![feature(deref_patterns)] @@ -50,20 +49,14 @@ mod prelude { } } -//! inner single-line doc comment -/*! +/// inner single-line doc comment +/** * inner multi-line doc comment */ #[doc = "inner doc attribute"] #[allow(dead_code, unused_variables)] #[no_std] -mod attributes {//! inner single-line doc comment - /*! - * inner multi-line doc comment - */ - #![doc = "inner doc attribute"] - #![allow(dead_code, unused_variables)] - #![no_std] +mod attributes { /// outer single-line doc comment /** @@ -349,7 +342,6 @@ mod expressions { - // concat_idents is deprecated @@ -405,31 +397,33 @@ mod expressions { fn expr_format_args() { let expr; format_arguments::new_const(&[]); - format_arguments::new_v1(&[""], - &[format_argument::new_display(&expr)]); + { + super let args = [format_argument::new_display(&expr)]; + format_arguments::new_v1(&[""], &args) + }; } } mod items { /// ItemKind::ExternCrate - mod item_extern_crate {/// ItemKind::ExternCrate + mod item_extern_crate { extern crate core; extern crate self as unpretty; extern crate core as _; } /// ItemKind::Use - mod item_use {/// ItemKind::Use + mod item_use { use ::{}; use crate::expressions; use crate::items::item_use; use core::*; } /// ItemKind::Static - mod item_static {/// ItemKind::Static + mod item_static { static A: () = { }; static mut B: () = { }; } /// ItemKind::Const - mod item_const {/// ItemKind::Const + mod item_const { const A: () = { }; trait TraitItems { const @@ -443,7 +437,7 @@ mod items { } } /// ItemKind::Fn - mod item_fn {/// ItemKind::Fn + mod item_fn { const unsafe extern "C" fn f() { } async unsafe extern "C" fn g() -> @@ -458,21 +452,19 @@ mod items { } } /// ItemKind::Mod - mod item_mod {/// ItemKind::Mod - } + mod item_mod { } /// ItemKind::ForeignMod - mod item_foreign_mod {/// ItemKind::ForeignMod + mod item_foreign_mod { extern "Rust" { } extern "C" { } } /// ItemKind::GlobalAsm: see exhaustive-asm.rs /// ItemKind::TyAlias - mod item_ty_alias {/// ItemKind::GlobalAsm: see exhaustive-asm.rs - /// ItemKind::TyAlias + mod item_ty_alias { type Type<'a> where T: 'a = T; } /// ItemKind::Enum - mod item_enum {/// ItemKind::Enum + mod item_enum { enum Void { } enum Empty { Unit, @@ -488,7 +480,7 @@ mod items { } } /// ItemKind::Struct - mod item_struct {/// ItemKind::Struct + mod item_struct { struct Unit; struct Tuple(); struct Newtype(Unit); @@ -499,45 +491,40 @@ mod items { } } /// ItemKind::Union - mod item_union {/// ItemKind::Union + mod item_union { union Generic<'a, T> where T: 'a { t: T, } } /// ItemKind::Trait - mod item_trait {/// ItemKind::Trait + mod item_trait { auto unsafe trait Send { } trait Trait<'a>: Sized where Self: 'a { } } /// ItemKind::TraitAlias - mod item_trait_alias {/// ItemKind::TraitAlias + mod item_trait_alias { trait Trait = Sized where for<'a> T: 'a; } /// ItemKind::Impl - mod item_impl {/// ItemKind::Impl + mod item_impl { impl () { } impl () { } impl Default for () { } impl const Default for () { } } /// ItemKind::MacCall - mod item_mac_call {/// ItemKind::MacCall - } + mod item_mac_call { } /// ItemKind::MacroDef - mod item_macro_def {/// ItemKind::MacroDef + mod item_macro_def { macro_rules! mac { () => {...}; } macro stringify { () => {} } } /// ItemKind::Delegation - /*! FIXME: todo */ - mod item_delegation {/// ItemKind::Delegation - /*! FIXME: todo */ - } + /** FIXME: todo */ + mod item_delegation { } /// ItemKind::DelegationMac - /*! FIXME: todo */ - mod item_delegation_mac {/// ItemKind::DelegationMac - /*! FIXME: todo */ - } + /** FIXME: todo */ + mod item_delegation_mac { } } mod patterns { /// PatKind::Missing @@ -688,29 +675,33 @@ mod types { /// TyKind::Paren fn ty_paren() { let _: T; } /// TyKind::Typeof - /*! unused for now */ + /** unused for now */ fn ty_typeof() { } /// TyKind::Infer fn ty_infer() { let _: _; } /// TyKind::ImplicitSelf - /*! there is no syntax for this */ + /** there is no syntax for this */ fn ty_implicit_self() { } /// TyKind::MacCall - #[expect(deprecated)] - fn ty_mac_call() { let _: T; let _: T; let _: T; } + fn ty_mac_call() { + macro_rules! ty { ($ty:ty) => { $ty } } + let _: T; + let _: T; + let _: T; + } /// TyKind::CVarArgs - /*! FIXME: todo */ + /** FIXME: todo */ fn ty_c_var_args() { } /// TyKind::Pat fn ty_pat() { let _: u32 is 1..=RangeMax; } } mod visibilities { /// VisibilityKind::Public - mod visibility_public {/// VisibilityKind::Public + mod visibility_public { struct Pub; } /// VisibilityKind::Restricted - mod visibility_restricted {/// VisibilityKind::Restricted + mod visibility_restricted { struct PubCrate; struct PubSelf; struct PubSuper; diff --git a/tests/ui/unpretty/exhaustive.rs b/tests/ui/unpretty/exhaustive.rs index 60ad3564689d..ccf907a61653 100644 --- a/tests/ui/unpretty/exhaustive.rs +++ b/tests/ui/unpretty/exhaustive.rs @@ -11,7 +11,6 @@ #![feature(auto_traits)] #![feature(box_patterns)] #![feature(builtin_syntax)] -#![feature(concat_idents)] #![feature(const_trait_impl)] #![feature(decl_macro)] #![feature(deref_patterns)] @@ -835,11 +834,13 @@ mod types { } /// TyKind::MacCall - #[expect(deprecated)] // concat_idents is deprecated fn ty_mac_call() { - let _: concat_idents!(T); - let _: concat_idents![T]; - let _: concat_idents! { T }; + macro_rules! ty { + ($ty:ty) => { $ty } + } + let _: ty!(T); + let _: ty![T]; + let _: ty! { T }; } /// TyKind::CVarArgs diff --git a/tests/ui/unpretty/flattened-format-args.stdout b/tests/ui/unpretty/flattened-format-args.stdout index a5d943281ad8..4af82924c7b4 100644 --- a/tests/ui/unpretty/flattened-format-args.stdout +++ b/tests/ui/unpretty/flattened-format-args.stdout @@ -10,7 +10,9 @@ fn main() { let x = 1; // Should flatten to println!("a 123 b {x} xyz\n"): { - ::std::io::_print(format_arguments::new_v1(&["a 123 b ", " xyz\n"], - &[format_argument::new_display(&x)])); + ::std::io::_print({ + super let args = [format_argument::new_display(&x)]; + format_arguments::new_v1(&["a 123 b ", " xyz\n"], &args) + }); }; } diff --git a/tests/ui/unsized-locals/yote.rs b/tests/ui/unsized-locals/yote.rs index aa5b68a30782..1de75a6ce617 100644 --- a/tests/ui/unsized-locals/yote.rs +++ b/tests/ui/unsized-locals/yote.rs @@ -1,4 +1,2 @@ -//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION" - #![feature(unsized_locals)] //~ERROR feature has been removed #![crate_type = "lib"] diff --git a/tests/ui/unsized-locals/yote.stderr b/tests/ui/unsized-locals/yote.stderr index 655aad5360cc..8e7da64038a4 100644 --- a/tests/ui/unsized-locals/yote.stderr +++ b/tests/ui/unsized-locals/yote.stderr @@ -1,10 +1,10 @@ error[E0557]: feature has been removed - --> $DIR/yote.rs:3:12 + --> $DIR/yote.rs:1:12 | LL | #![feature(unsized_locals)] | ^^^^^^^^^^^^^^ feature has been removed | - = note: removed in CURRENT_RUSTC_VERSION (you are using $RUSTC_VERSION) + = note: removed in CURRENT_RUSTC_VERSION = note: removed due to implementation concerns; see https://github.com/rust-lang/rust/issues/111942 error: aborting due to 1 previous error diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs index 53f07a94fd15..ad7d972879ff 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs @@ -5,7 +5,6 @@ trait Trait { //~^ ERROR the name `N` is already used for a generic parameter in this item's generic parameters //~| ERROR expected value, found builtin type `u32` //~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - //~| ERROR associated item referring to unboxed trait object for its own trait bar //~^ ERROR cannot find value `bar` in this scope } diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr index a085dd6ac576..e10bb98c1349 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr @@ -20,7 +20,7 @@ LL | fn fnc(&self) -> dyn Trait { | ^^^ not a value error[E0425]: cannot find value `bar` in this scope - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:9:9 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:8:9 | LL | bar | ^^^ not found in this scope @@ -45,22 +45,7 @@ error: defaults for const parameters are only allowed in `struct`, `enum`, `type LL | fn fnc(&self) -> dyn Trait { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: associated item referring to unboxed trait object for its own trait - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:4:48 - | -LL | trait Trait { - | ----- in this trait -... -LL | fn fnc(&self) -> dyn Trait { - | ^^^^^^^^^ - | -help: you might have meant to use `Self` to refer to the implementing type - | -LL - fn fnc(&self) -> dyn Trait { -LL + fn fnc(&self) -> Self { - | - -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0391, E0403, E0423, E0425. For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/wf/issue-87495.stderr b/tests/ui/wf/issue-87495.stderr index 0c293e3576d6..bf79535df116 100644 --- a/tests/ui/wf/issue-87495.stderr +++ b/tests/ui/wf/issue-87495.stderr @@ -13,6 +13,11 @@ LL | trait T { LL | const CONST: (bool, dyn T); | ^^^^^ ...because it contains this associated `const` = help: consider moving `CONST` to another trait +help: you might have meant to use `Self` to refer to the implementing type + | +LL - const CONST: (bool, dyn T); +LL + const CONST: (bool, Self); + | error: aborting due to 1 previous error diff --git a/triagebot.toml b/triagebot.toml index 98eb99d9c607..6385528e7b6e 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1023,6 +1023,10 @@ Otherwise, you can ignore this comment. [mentions."src/tools/x"] message = "`src/tools/x` was changed. Bump version of Cargo.toml in `src/tools/x` so tidy will suggest installing the new version." +[mentions."src/tools/tidy"] +message = "There are changes to the `tidy` tool." +cc = ["@jieyouxu"] + [mentions."src/tools/tidy/src/deps.rs"] message = "The list of allowed third-party dependencies may have been modified! You must ensure that any new dependencies have compatible licenses before merging." cc = ["@davidtwco", "@wesleywiser"] @@ -1164,7 +1168,7 @@ cc = ["@ehuss"] [mentions."src/doc/rustc-dev-guide"] message = "The rustc-dev-guide subtree was changed. If this PR *only* touches the dev guide consider submitting a PR directly to [rust-lang/rustc-dev-guide](https://github.com/rust-lang/rustc-dev-guide/pulls) otherwise thank you for updating the dev guide with your changes." -cc = ["@BoxyUwU", "@jieyouxu", "@kobzol"] +cc = ["@BoxyUwU", "@jieyouxu", "@kobzol", "@tshepang"] [mentions."compiler/rustc_codegen_ssa/src/codegen_attrs.rs"] cc = ["@jdonszelmann"]